const ruleStr = [
'DTSTART;TZID=America/Los_Angeles:20190603T181500',
'RRULE:FREQ=WEEKLY;WKST=SU;BYDAY=MO,TU,WE,FR,SA'
].join('\n')
const rule = RRule.fromString(ruleStr)
const result = rule.between(
new Date('2019-07-16T07:00:00.000-07:00'),
new Date('2019-07-23T07:00:00.000-07:00')
)
console.log(result)
λ€μμ μΆλ ₯ν©λλ€.
0:Tue Jul 16 2019 15:15:00 GMT-0500 (CDT) {}
1:Wed Jul 17 2019 15:15:00 GMT-0500 (CDT) {}
2:Fri Jul 19 2019 15:15:00 GMT-0500 (CDT) {}
3:Sat Jul 20 2019 15:15:00 GMT-0500 (CDT) {}
4:Mon Jul 22 2019 15:15:00 GMT-0500 (CDT) {}
15:15:00 GMT-0500 (CDT)
λ 17:15 PDTμ΄κ³ DTSTARTλ DTSTART;TZID=America/Los_Angeles:20190603T181500
@davidgoliμ μν΄ κ΅¬νλ tzid
μ€μ νλ©΄ λ€λ₯Έ κ²°κ³Όκ° λνλ©λλ€.
const ruleStr = [
'DTSTART:20190603T181500',
'RRULE:FREQ=WEEKLY;WKST=SU;BYDAY=MO,TU,WE,FR,SA'
].join('\n')
const rule = RRule.fromString(ruleStr)
const ruleSet = new RRuleSet()
ruleSet.rrule(rule)
ruleSet.tzid('America/Los_Angeles')
const result = ruleSet.between(
new Date('2019-07-16T07:00:00.000-07:00'),
new Date('2019-07-23T07:00:00.000-07:00')
)
console.log(result)
0:Tue Jul 16 2019 13:15:00 GMT-0500 (CDT) {}
1:Wed Jul 17 2019 13:15:00 GMT-0500 (CDT) {}
2:Fri Jul 19 2019 13:15:00 GMT-0500 (CDT) {}
3:Sat Jul 20 2019 13:15:00 GMT-0500 (CDT) {}
4:Mon Jul 22 2019 13:15:00 GMT-0500 (CDT) {}
μμ κ²°κ³Όλ λ€μκ³Ό κ°μ΅λλ€.
0:Tue Jul 16 2019 20:15:00 GMT-0500 (CDT) {}
1:Wed Jul 17 2019 20:15:00 GMT-0500 (CDT) {}
2:Fri Jul 19 2019 20:15:00 GMT-0500 (CDT) {}
3:Sat Jul 20 2019 20:15:00 GMT-0500 (CDT) {}
4:Mon Jul 22 2019 20:15:00 GMT-0500 (CDT) {}
κ·Έ μ΄μ λ 무μμ
λκΉ?
κ·μΉ λ²μ : 2.6.2
CDT μκ°λμμ λ
Έλλ₯Ό μ€νν©λλ€. λ΄ μμ€ν
μκ°λλ America/Los_Angeles
μ΄ μ μ₯μλ₯Ό 볡μ νκ³ λ€μ ν μ€νΈλ₯Ό μΆκ°νμ΅λλ€.
it('generates correct recurrences when recurrence is WEEKLY and has BYDAY specified', () => {
const rrule = new RRule({
freq: RRule.WEEKLY,
dtstart: new Date(Date.UTC(2019, 6, 17, 18, 0, 0)),
tzid: 'America/Los_Angeles',
count: 10,
interval: 1,
wkst: RRule.SU,
byweekday: [RRule.MO, RRule.TU, RRule.WE, RRule.FR, RRule.SA]
})
expect(rrule.all()).to.deep.equal([
new Date('2019-07-17T18:00:00.000-07:00'), // WE
new Date('2019-07-19T18:00:00.000-07:00'), // FR
new Date('2019-07-20T18:00:00.000-07:00'), // SA
new Date('2019-07-22T18:00:00.000-07:00'), // MO
new Date('2019-07-23T18:00:00.000-07:00'), // TU
new Date('2019-07-24T18:00:00.000-07:00'),
new Date('2019-07-26T18:00:00.000-07:00'),
new Date('2019-07-27T18:00:00.000-07:00'),
new Date('2019-07-29T18:00:00.000-07:00'),
new Date('2019-07-30T18:00:00.000-07:00')
])
})
UTC μκ°λμμ μ€νν λλ§ μ±κ³΅ν©λλ€ ( "env": { "TZ": "UTC" }
in launch.json
). λ€λ₯Έ μκ°λμμλ ν
μ€νΈκ° μ€ν¨ν©λλ€.
@davidgoli κ° μλν κ²μ΄λ©° μ¬κΈ°μ λκ° λΉ μ‘μ΅λκΉ? κ·Έλ λ€λ©΄ tzid
맀κ°λ³μλ₯Ό μ¬λ°λ₯΄κ² μ¬μ©νλ λ°©λ²μ 무μμ
λκΉ? rrule
μ§μ λ μκ°λμμ μ€νλλλ‘ μΆκ°ν κ² κ°μ΅λλ€.
λμΌν λ¬Έμ κ° μμ§λ§ rrule.all()μ΄ μμ΅λλ€. UTCλ μλνμ§λ§ λ€λ₯Έ μκ°λλ μ€νμ μ μ μ©νμ§ μμμΌ ν λ λ€μ μ μ©ν©λλ€.
rrule-tz.jsμ 1849νκ³Ό κ΄λ ¨μ΄ μμ μ μμ΅λλ€.
var rezonedDate = rezoneIfNeeded(res, options);
rezoneIfNeeded
λ μ΄λ¦κ³Ό λ¬λ¦¬ κ²μ¬λ₯Ό μννμ§ μμΌλ©° UTCκ° μλ ν νμ μμμ μ¬μ‘°μ ν©λλ€.
function rezoneIfNeeded(date, options) {
return new datewithzone_DateWithZone(date, options.tzid).rezonedDate();
}
μ΄λ―Έ μ¬λ°λ₯΄κ² ꡬμνλμ΄ μλλ°λ λ μ§ κ΅¬μμ λ³κ²½νλ κ² κ°μ΅λλ€.
rezonedDate()
λ₯Ό λ¨μν this.date
λ₯Ό λ°ννλλ‘ λ³κ²½νλ©΄ λ¬Έμ κ° ν΄κ²°λλ κ² κ°μ΅λλ€. λ΄κ° λ€λ₯Έ κ³³μμ 무μΈκ°λ₯Ό κΉ¨λ¨λ Έλ€κ³ μμ ν νμ ν μλ μμ§λ§, μΌν 보기μλ μ΄ λ³κ²½μ΄ μ΄λ£¨μ΄μ§λ©΄ λ€λ₯Έ λͺ¨λ κ²μ΄ μ μλνλ κ²μ²λΌ 보μ
λλ€.
rrule-tz.jsμ 1849νκ³Ό κ΄λ ¨μ΄ μμ μ μμ΅λλ€.
var rezonedDate = rezoneIfNeeded(res, options);
rezoneIfNeeded
λ μ΄λ¦κ³Ό λ¬λ¦¬ κ²μ¬λ₯Ό μννμ§ μμΌλ©° UTCκ° μλ ν νμ μμμ μ¬μ‘°μ ν©λλ€.
function rezoneIfNeeded(date, options) { return new datewithzone_DateWithZone(date, options.tzid).rezonedDate(); }
μ΄λ―Έ μ¬λ°λ₯΄κ² ꡬμνλμ΄ μλλ°λ λ μ§ κ΅¬μμ λ³κ²½νλ κ² κ°μ΅λλ€.
μ΄κ²μ μ ννμ§ μμ΅λλ€. rezonedDate
λ©μλλ tzid
κ° μ€μ λμ΄ μλμ§ νμΈνμ¬ μμ μ€νμ
μ μ μ©ν μ§ μ¬λΆλ₯Ό κ²°μ ν©λλ€.
@agordeev μ΄ λ¬Έμ λ₯Ό μ‘°μ¬νκ² μ΅λλ€. @hlee5zebra μ λ¨μν μκ°λ μ§μμ μ κ±°νλ "μμ "μ νμνμ§ μμμ΅λλ€. λ κ²½μ° λͺ¨λ tzid
맀κ°λ³μλ₯Ό μ¬μ©νμ§ μμΌλ©΄ μμν κ²°κ³Όλ₯Ό μ»μ΅λκΉ?
κ·ΈλΌμλ λΆκ΅¬νκ³ RRuleκ³Ό RRuleSet λμ κ°μ λΆμΌμΉλ μ μ κ΄λ ¨μ΄ μμΌλ©° λ μμΈν μ΄ν΄λ΄μΌ ν λ²κ·ΈμΌ μ μμ΅λλ€. ν μ€νΈ μΌμ΄μ€ κ°μ¬ν©λλ€!
λ΄ λ¬Έμ λ‘ μ΄μ΄μ§ λ¬Έμ κ° μμ΅λλ€. λ΄ μλ² μ½λκ° DTSTART κ° μκ°μ μ¬λ°λ₯΄κ² μ²λ¦¬νμ§ μκ³ TZIDλ‘ μ§μ λ μκ°λμ νμ§νν΄μΌ ν λ UTCλ‘ μ λ¬νμ΅λλ€. μλ§λ @agordeev λ¬Έμ μ λμμ΄ λ κ²μ λλ€. μ λ₯Ό μ¬λ°λ₯Έ λ°©ν₯μΌλ‘ μλ΄ν΄ μ£Όμ @davidgoli μκ² κ°μ¬λ립λλ€.
μ½λλ² μ΄μ€μμ λ¬Έμ λ₯Ό λ°κ²¬ν κ² κ°μ΅λλ€. toString()
λ©μλ datewithzone.ts
TZIDκ° κ³΅κΈλλ μΆλ ₯ UTC μκ°μ, κ·Έ λμ μ μΆλ ₯ν΄μΌ κ΅λΆμ μκ° κ²μ΄λ€.
@hlee5zebra READMEμμ μ΄ ν μ€νΈλ₯Ό κΈ°λ‘ν΄ λμμμ€.
https://github.com/jakubroztocil/rrule#important -use-utc-dates
JavaScriptμ λ μ§λ κΉλ€λ‘μ΅λλ€. RRuleμ νμν μ 3μ μ’ μμ±μ ν¬κ² μΆκ°νμ§ μκ³ κ°λ₯ν ν λ§μ μ μ°μ±μ μ§μνλ €κ³ μλνμ§λ§ μ΄λ μ°λ¦¬μκ² λͺ κ°μ§ νΉλ³ν κ·μΉλ μμμ μλ―Έν©λλ€.
κΈ°λ³Έμ μΌλ‘ RRuleμ "λΆλ" μκ° λλ UTC μκ°λλ₯Ό λ€λ£Ήλλ€. νΉμ μκ°λμ κ²°κ³Όλ₯Ό μνλ κ²½μ° RRuleμ μκ°λ μ§μλ μ 곡ν©λλ€. μ΄λ μͺ½μ΄λ , JavaScriptμ λ΄μ₯ "μκ°λ" μ€νμ μ λ°©ν΄κ° λλ κ²½ν₯μ΄ μμΌλ―λ‘ μ΄ λΌμ΄λΈλ¬λ¦¬λ λ¨μν κ·Έκ²μ μ ν μ¬μ©νμ§ μμ΅λλ€. λͺ¨λ μκ°μ JavaScriptμ μ‘΄μ¬νμ§ μλ κ²μ²λΌ μ€νμ μ΄ 0μΈ μνλ‘ λ°νλ©λλ€.
κ²°λ‘ μ λ°νλ "UTC" λ μ§λ νμ νμ§ μκ°λμ λ μ§λ‘ ν΄μλλ€λ κ²μ λλ€. μ΄λ μ€νμ μ΄ μ μ©λ "μ¬λ°λ₯Έ" νμ§ μκ°μ μ»κΈ° μν΄ μΆκ° λ³νμ μνν΄μΌ ν¨μ μλ―Έν μ μμ΅λλ€.
μ΄λ¬ν μ΄μ λ‘ UTCλ‘ νμμ€ν¬νλ₯Ό μ¬μ©νλ κ²μ΄ μ’μ΅λλ€. μλ‘μ΄ λ μ§(Date.UTC(...)). λ°νλ λ μ§λ λ§μ°¬κ°μ§λ‘ UTCλ‘ νμλ©λλ€(νμ μκ°λ μ€νμ μ΄ μλ λ μ§λ₯Ό λ°ννλ Chrome μ μΈ).
μΆκ° μ£Όλ¦μ λλΆλΆμ JS ꡬνμ μμ΅λλ€. UTC μ€νμ
_λλ_ λ‘컬 μ€νμ
μ μ»μ§λ§ λ μ¬μ΄λ₯Ό μ νν μλ μμ΅λλ€. μ΄ λν ꡬνμ λ°λΌ λ€λ¦
λλ€. λ°λΌμ "UTC λ μ§"κ° λ°νλμ΄ μΌλΆ μμΉμμλ μ€νμ
μ΄ ν¬ν¨λ toString()
κ° μ 곡λκ³ λ€λ₯Έ μμΉμμλ ν¬ν¨λμ§ μμ μ μμ΅λλ€.
μλ₯Ό λ€μ΄ Chromeμμ:
> new Date(Date.UTC(2016, 10, 5))
Fri Nov 04 2016 17:00:00 GMT-0700 (Pacific Daylight Time)
νμ§λ§ λ Έλμμ:
> new Date(Date.UTC(2016, 10, 5))
2016-11-05T00:00:00.000Z
μ΄κ²μ΄ μ΅μμ κ²°κ³Όλ₯Ό μν΄ toString()
κ°μ 무μνκ³ toISOString()
λ° getUTCHours()
(etc) λ©μλλ§ μ¬μ©νλ μ΄μ μ
λλ€.
λͺ¨λ λ μ§μ λν΄ UTC λ°©λ²λ§ μ¬μ©νκ³ νμ§ μκ°μΌλ‘ "ν΄μ"νλ μ΄ μ κ·Ό λ°©μμ μ¬μ©νλ©΄ rruleμ μκ°λλ₯Ό κ³ λ €ν νμ μμ΄ rruleμ΄ λ°νν λ μ§ λ° μκ°μ κ· μΌνκ² μ‘μΈμ€ν μ μμ΅λλ€.
μ’μ, λλ μ΄ λ¬Έμ λ₯Ό μ¬νν μ μλλ‘ νκΈ° μν΄ rrule.all()
λ₯Ό μ½κ° μμ ν΄ μμΌλ©° λ€μμ μ΄ λ¬Έμ λ₯Ό μμ μ μΌλ‘ μ¬ννκΈ° μν΄ μ°Ύμ κ²μ
λλ€.
rrule.toString()
κ° μ ννκ² μΈμλ©λλ€:>> rRule.toString()
"DTSTART;TZID=America/Adak:20190718T000000
RRULE:FREQ=DAILY"
>> rRule.toString()
"DTSTART;TZID=America/Chicago:20190718T000000
RRULE:FREQ=DAILY"
>> rRule.toString()
"DTSTART;TZID=America/New_York:20190718T000000
RRULE:FREQ=DAILY"
>> rRule.toString()
"DTSTART:20190718T000000Z
RRULE:FREQ=DAILY"
건λ€μ§ iterator ν¨μλ₯Ό κ±·λ λμ rrule.all()
, μκΈ° μ νλΌλ―Έν°μ 첫λ²μ§Έ μΈμ€ν΄μ€ date
ν΄ μμ λ κ° κ²½μ°λ§λ€ μκ°λ λ€μ Date
ν΅ν΄ μΈμ .toISOString()
:
μλ©λ¦¬μΉ΄/μλ₯:
"2019-07-18T04:00:00.000Z"
λ―Έκ΅/μμΉ΄κ³ :
"2019-07-18T00:00:00.000Z"
λ―Έκ΅/λ΄μ:
"2019-07-17T23:00:00.000Z"
UTC:
"2019-07-18T00:00:00.000Z"
μκ°λκ° UTCλ‘ μ€μ λμ§ μμ κ²½μ°(μ: America/Adak, America/New_York) νμ§ μκ°κ³Ό μ νν μκ°λ μ¬μ΄μ μ€νμ μ DTSTART λ μ§μμ λΉΌλ κ²μ²λΌ 보μ λλ€. λ°λΌμ λ΄ νμ§ μκ°κ³Ό λ΄μ κ°μ μ€νμ μ΄ +1μ΄λ―λ‘ New York ISO λ¬Έμμ΄μ 23:00μ νμν©λλ€. μ΄ μ€νμ μ 2019λ 7μ 18μΌ μμ μμ λΉΌλ©΄ κ²°κ³Όλ 07/17μΌ μ€ν 11μκ° λ©λλ€. /2019.
νμ§λ§ UTCμμλ μ΄λ° μΌμ΄ λ°μνμ§ μλλ€λ μ μ μ μνμμμ€.
μ΄κ²μ΄ λ¬Έμ μΌ μ μλ€κ³ μκ°ν©λκΉ, μλλ©΄ λ΄κ° λμ³€μ μ μλ μνν΄μΌ νλ μΌλΆ ꡬμ±μ΄ μμ΅λκΉ?
λ΄κ° λ³Έ κ²μ λν ν΄κ²° λ°©λ²μΌλ‘ λ€μμ μννμΌλ©° JavaScriptμ Date
μ μ νν μΈμ€ν΄μ€λ₯Ό μμ μ μΌλ‘ μ»μ μ μλ κ² κ°μ΅λλ€.
rRule.all(function (date, i) {
if (this.getSelectedTzid() !== 'UTC') {
date = moment.tz({
year: date.getUTCFullYear(),
month: date.getUTCMonth(),
date: date.getUTCDate(),
hours: date.getUTCHours(),
minutes: date.getUTCMinutes()
}, this.getLocalTzid()).toDate();
}
...
}.bind(this));
@hlee5zebra μ, getUTCxxx
λ°©λ²μ μ¬μ©νλ μ κ·Ό λ°©μμ readmeμμ κΆμ₯νλ μ¬λ°λ₯Έ μ κ·Ό λ°©μμ
λλ€.
μ μ¬ UTC λ μ§λ UTC μκ°μΌλ‘ κ±°μ _μ€μ λ‘_ λμ§ μμ΅λλ€. UTCλ "μ€λ¦½" μκ°λκ° λλλ‘ μ€λ²λ‘λλλ―λ‘ getUTCxxx
λ©μλλ₯Ό μ¬μ©νμ¬ μλ μκ°λμ κ΄κ³μμ΄ _local_ μκ°μ κ²μν μ μμ΅λλ€. μ΄λ¬ν μ΄μ λ‘ tzid
λ₯Ό μ¬μ©νμ§ μκ³ λ νμ§ νμ€ μκ°λμμ νμ§ νμ€ μκ°λλ₯Ό μ¬μ©νλ κ²κ³Ό λμΌν λμμ μμν΄μΌ ν©λλ€. tzid
λ _λ€λ₯Έ μκ°λμμ_ λνμ΄λλ νμ¬ νμ§ μκ°μ κ°μ Έμ€λ λ°λ§ μ¬μ©ν΄μΌ ν©λλ€. νμ μ¬μ©μμ νμ§ μκ°λλ‘ λνμ΄νλ €λ©΄ tzid
λ©λλ€.
μ΄κ²μ΄ μ΄ λΌμ΄λΈλ¬λ¦¬λ₯Ό λ€μ μμ±ν λ λ΄μ₯ JS Date κ°μ²΄λ₯Ό μ ν μ¬μ©νμ§ μλ μ΄μ μ λλ€. λ무 νΌλμ€λ½κΈ°λ§ ν©λλ€.
@agordeev μ΄ λ¬Έμ λ₯Ό μ‘°μ¬νκ² μ΅λλ€. @hlee5zebra μ λ¨μν μκ°λ μ§μμ μ κ±°νλ "μμ "μ νμνμ§ μμμ΅λλ€. λ κ²½μ° λͺ¨λ tzid 맀κ°λ³μλ₯Ό μ¬μ©νμ§ μμΌλ©΄ μμν κ²°κ³Όλ₯Ό μ»μ΅λκΉ?
λ΅λ³ κ°μ¬ν©λλ€.
const rrule = new RRule({
freq: RRule.WEEKLY,
dtstart: new Date(Date.UTC(2019, 6, 17, 18, 0, 0)),
// tzid: 'America/Los_Angeles',
count: 10,
interval: 1,
wkst: RRule.SU,
byweekday: [RRule.MO, RRule.TU, RRule.WE, RRule.FR, RRule.SA]
})
μμ°:
- [Date: 2019-07-17T18:00:00.000Z]
- [Date: 2019-07-19T18:00:00.000Z]
- [Date: 2019-07-20T18:00:00.000Z]
- [Date: 2019-07-22T18:00:00.000Z]
etc..
λ°λΌμ λ μ§/μκ°μ μ ννμ§λ§ μκ°λλ UTCμ λλ€. rruleμ tzid 맀κ°λ³μλ₯Ό μλ΅ν λ UTCμ DTSTARTλ₯Ό κ³ λ €ν©λλ€.
νμ μ¬μ©μμ νμ§ μκ°λλ‘ λνμ΄νλ €λ©΄ tzidλ₯Ό μ¬μ©νλ©΄ μ λ©λλ€.
μ¬μ©μμ μκ°λμμ λνμ΄νλ μ μΌν μ΅μ μ ν΄λΉ μκ°λλ₯Ό tzid 맀κ°λ³μλ‘ μ λ¬νλ κ²λΏμ΄λΌκ³ μκ°νμ΅λλ€. λΌμ΄λΈλ¬λ¦¬λ μλ²μμ node.jsμ ν¨κ» μ¬μ©λλ€λ μ μ μΌλμ λμμμ€.
_μκ°λμ κ΄κ³μμ΄_ μ¬μ©μμ νμ§ μκ°μΌλ‘ λ°λ³΅μ΄ 1800μ μμ κ²½μ° tzid
λ₯Ό μ¬μ©ν νμκ° μμ΅λλ€. README: https://github.com/jakubroztocil/rrule#important -use-utc-datesμ μ€λͺ
λ "λΆλ" μκ°μ λν΄ μ½μλμ§ νμΈνμμμ€.