ํ๋ก ํธ์๋์์ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ(v2.5.6)์ ๋์์ ๋ฐฑ์๋์์ ๋๋ฑํ PHP ๋ผ์ด๋ธ๋ฌ๋ฆฌ (v2.3.3)์ ๋น๊ตํ์ต๋๋ค. ์ผ๊ด ์ ์ฝ ์๊ฐ์ ๋ณ๊ฒฝ์ด ์ฒ๋ฆฌ๋๋ ๋ฐฉ์์๋ ๋ถ๋ช ํ ๋ถ์ผ์น๊ฐ ์์ผ๋ฉฐ PHP ๋ฒ์ ์ด ์ด๋ฅผ ๋ ์ ์ฒ๋ฆฌํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
America/Denver
์๊ฐ๋์์ 2018๋
11์ 4์ผ ์ผ์์ผ์ ์ผ๊ด ์ ์ฝ ์๊ฐ์ ๊ฐ ์ ์ฉ๋ฉ๋๋ค(GMT-6์์ GMT-7๋ก ๋ณ๊ฒฝ). ๋ฐ๋ผ์ ์คํ 1์์ ์์ํ์ฌ ์๊ฐ ์ ํ ์ ์ธ 11์ 1์ผ๋ถํฐ ๋งค์ฃผ ์, ์, ๋ชฉ์ ๋ฐ๋ณต๋๋ ๋ฐ๋ณต ์๋ฆฌ์ฆ๋ฅผ ์ค์ ํด ๋ณด๊ฒ ์ต๋๋ค.
RRule.fromString(
"DTSTART;TZID=America/Denver:20181101T190000;\n"
+ "RRULE:FREQ=WEEKLY;BYDAY=MO,WE,TH;INTERVAL=1;COUNT=7"
).all()
์ด ๊ฒฝ์ฐ ์๋์ ๊ฐ์ด ๋ชจ๋ ๋ฐ๋ณต์ด ์คํ 1์์ ์์๋ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค. (๋ฌธ์์ ๋ฐ๋ฅด๋ฉด Luxon ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ์ด๋ป๊ฒ๋ ์ด๊ธฐํํด์ผ ํ๋ค๋ ๋ด์ฉ์ ๋ณด์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ์์ฌ๋ฅผ ํตํด ์ฌ๋ฐ๋ฅด๊ฒ "์ค์น"๋์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.)
์์ ๊ฒฐ๊ณผ(๋ชจ๋ 13:00:00์ ์์):
(7)ย [
Thu Nov 01 2018 13:00:00 GMT-0600 (Mountain Daylight Time),
Mon Nov 05 2018 13:00:00 GMT-0700 (Mountain Standard Time),
Wed Nov 07 2018 13:00:00 GMT-0700 (Mountain Standard Time),
Thu Nov 08 2018 13:00:00 GMT-0700 (Mountain Standard Time),
Mon Nov 12 2018 13:00:00 GMT-0700 (Mountain Standard Time),
Wed Nov 14 2018 13:00:00 GMT-0700 (Mountain Standard Time),
Thu Nov 15 2018 13:00:00 GMT-0700 (Mountain Standard Time)
]
์ค์ ๊ฒฐ๊ณผ:
(7)ย [
Thu Nov 01 2018 13:00:00 GMT-0600 (Mountain Daylight Time),
Mon Nov 05 2018 12:00:00 GMT-0700 (Mountain Standard Time), <-- Should be 13:00:00
Wed Nov 07 2018 12:00:00 GMT-0700 (Mountain Standard Time), <-- same
Thu Nov 08 2018 12:00:00 GMT-0700 (Mountain Standard Time), <-- same
Mon Nov 12 2018 12:00:00 GMT-0700 (Mountain Standard Time), <-- same
Wed Nov 14 2018 12:00:00 GMT-0700 (Mountain Standard Time), <-- same
Thu Nov 15 2018 12:00:00 GMT-0700 (Mountain Standard Time) <-- same
]
PHP ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๋น์ทํ ์ํฉ์ ์ค์ ํ์ ๋ ๊ฒฐ๊ณผ๋ ์์์ ์์ํ ๋๋ก์์ผ๋ฉฐ ๋ชจ๋ ์ธ์คํด์ค ๋ UTC๊ฐ ์๋ America/Denver ์๊ฐ๋์์ 13:00:00์ ์์ํ์ต๋๋ค.
๊ธฐํ ์ธ๋ถ ์ฌํญ:
ํธ์ง: ์คํ ์์
์ฝ์ ๊ฒฝ๊ณ ๊ฐ ํ์๋ฉ๋๊น? ์:
'Using TZID without Luxon available is unsupported. Returned times are in UTC, not the requested time zone'
Luxon์ optionalDependencies
์ ์์ผ๋ฏ๋ก node_modules
์ ์์ผ๋ฉด ๊ฐ์ ธ์ค๊ณ ๊ทธ๋ ์ง ์์ผ๋ฉด ๊ฐ์ ธ์ต๋๋ค.
rrule ํ ์คํธ ์ค์ํธ์์ ์ฝ๋๋ฅผ ์คํํ๋ฉด ๋ค์์ ์ป์ต๋๋ค.
[
[Date: 2018-11-01T19:00:00.000Z]
[Date: 2018-11-05T19:00:00.000Z]
[Date: 2018-11-07T19:00:00.000Z]
[Date: 2018-11-08T19:00:00.000Z]
[Date: 2018-11-12T19:00:00.000Z]
[Date: 2018-11-14T19:00:00.000Z]
[Date: 2018-11-15T19:00:00.000Z]
]
๊ทํ๊ฐ ์์ฒญํ ์๊ฐ์ด ๋ด๋ฒ ์๊ฐ๋์ 1900์์ด๊ธฐ ๋๋ฌธ์ ์์ํ ๋๋ก์
๋๋ค. (์ด๊ฒ์ PHP๊ฐ ์๋๋ผ JavaScript์ด๊ธฐ ๋๋ฌธ์ ๋ก์ปฌ ๋จธ์ ์๊ฐ๋ ๋๋ UTC ์ด์ธ์ ์๊ฐ๋์์๋ Date
๊ฐ์ฒด๋ฅผ ์ ๊ณตํ ์ ์์ผ๋ฏ๋ก UTC๋ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํญ์ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค.)
UTC ๋ ์ง๊ฐ ์๋ ํ์ง(MST/MDT) ๋ ์ง๊ฐ ํ์๋๋ค๋ ์ฌ์ค์ด ์ฝ๊ฐ ๋นํฉ์ค๋ฝ์ต๋๋ค. ๋ด๊ฐ ์๋ ํ, ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํ์ฌ UTC ๋ ์ง๋ง ๋ฐํํ๋๋ก ๊ตฌ์ฑ๋์ด ์์ง๋ง ์ด์ ์๋ ๋์ ํ์ง ๋ ์ง๋ฅผ ๋ฐํํ๋ ๋ฐ ์ฌ์ฉ๋์์ต๋๋ค.
์ฝ์ ๊ฒฝ๊ณ ๊ฐ ํ์๋ฉ๋๊น? ์:
'์ฌ์ฉ ๊ฐ๋ฅํ Luxon ์์ด TZID๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ง์๋์ง ์์ต๋๋ค. ๋ฐํ๋ ์๊ฐ์ ์์ฒญํ ์๊ฐ๋๊ฐ ์๋๋ผ UTC์ ๋๋ค'
์ฝ์ ๊ฒฝ๊ณ ๊ฐ ์์ต๋๋ค. Luxon์ด ์ ๋๋ก ์ ๊ณต๋๋ ๊ฒ ๊ฐ์ต๋๋ค.
์๊ฐ๋์ ๊ดํด์๋ Chrome devtools ์ฝ์ ๋ช ๋ น์ค์์ ์ง์ ์ฝ๋๋ฅผ ์คํํ ๊ฒฐ๊ณผ MST/DST๊ฐ ํ์๋ฉ๋๋ค.
๋จ๊ณ: Chrome ์ด๊ธฐ --> RRule ๋ฐ Luxon์ด ์ ๊ณต๋ ํ์ด์ง๋ก ์ด๋ --> Cmd+Opt+I --> "์ฝ์" ํญ --> ์ ์ค๋ํซ์ ๋ณต์ฌํ์ฌ ๋งจ ์๋์ ๋ช ๋ น์ค์ ๋ถ์ฌ๋ฃ๊ธฐ --> Enter
์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํ์ฌ UTC ๋ ์ง๋ง ๋ฐํํ๋๋ก ๊ตฌ์ฑ๋์ด ์์ง๋ง ์ด์ ์๋ ๋์ ํ์ง ๋ ์ง๋ฅผ ๋ฐํํ๋ ๋ฐ ์ฌ์ฉ๋์์ต๋๋ค.
์ด๊ฒ ์ด๋ ๋ฒ์ ์์ ๋ฐ๋์๋์ง ์์ธ์? ์ ๊ทธ๋ฐ ๋ณํ๊ฐ ์ผ์ด๋๊ฒ ์ต๋๊น? UTC ๋ ์ง ๋ง ๋ฐํํ๋ฉด ์ค์ ๋ก ์ด ์ผ๊ด ์ ์ฝ ์๊ฐ์ ๋ถ์ผ์น ๊ฐ ๋ฐ์ ํฉ๋๋ค! ํญ์ 13:00 UTC์ ๋ฐ์ํ๋ ์ด๋ฒคํธ๋ ์ด๋ฒคํธ๊ฐ ์ผ๊ด ์ ์ฝ ์๊ฐ์ ์ ํ ์ /ํ ๋ค๋ฅธ ์๊ฐ์ ์์๋๋๋ก ๋ณด์ฅํฉ๋๋ค. ์ด ๋ณ๊ฒฝ ์ฌํญ์ ๋๋๋ฆฌ๊ฑฐ๋ ์ผ๊ด ์ ์ฝ ์๊ฐ์ ๋ฅผ ๊ณ์ฐํ ์ ์๋ ๋ค๋ฅธ ๋์ฒด ๋ฐฉ๋ฒ์ ์ ๊ณตํด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. UTC๋ ๋งค์ฐ ์ ์ฉํ์ง๋ง ๋ชจ๋ ์ํฉ์์ ํญ์ ์ฌ๋ฐ๋ฅธ ์ ๊ทผ ๋ฐฉ์์ ์๋๋๋ค. ๋ํ์ด๋๋ ์ด๋ฒคํธ๋ก ์์ ํ ๋๋ ์ผ๊ด ์ ์ฝ ์๊ฐ์ ๊ฐ ์ ์ฉ ๋๊ธฐ ๋๋ฌธ์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ ํน์ ์๊ฐ๋๋ฅผ ๊ณ ๋ คํด์ผ ํฉ๋๋ค.
์ค์ ๋ก Node.js์์์ Chrome์์ ๋ค๋ฅธ ๋์์ ์ป์ต๋๋ค.
๋๋ ๋น์ ์ ์ฃผ์ด์ง "์์"์ถ๋ ฅ์ด ์ ๋น์ ์ด ์ ๋ง๋ก ๊ธฐ๋ํ๋ ๊ฒ์ธ์ง ์ดํดํ ์ ์๋ค๊ณ ๋งํ๊ณ ์ถ์ต๋๋ค. ํด๋น ์๊ฐ์ด ์๋ชป ํ์๋ฉ๋๋ค.
์ฌ๋ฐ๋ฅธ ๊ฒ์_ ์ฃผ์ด์ง ํ์ง ์๊ฐ์ ๊ฐ ์๊ฐ์ ๋ํ TZ ์คํ์ ์ ์ถ๊ฐํ ๊ฒฝ์ฐ์ ์๊ฐ์ ๋๋ค. ๊ทธ๋ฌ๋ฉด ๋ชจ๋ ์๊ฐ์ 19:00์ด ๋ฉ๋๋ค. ์ด๊ฒ์ด RRule์ด UTC๋ฅผ ๋ค๋ฃจ๋ ์ด์ ์ด๋ฉฐ UTC์ ์ฌ์ฉ์ด ์ด ํน์ ๋ฒ๊ทธ์ ์๋ฌด ๊ด๋ จ์ด ์๋ ์ด์ ์ ๋๋ค.
์ค์ ๋ก ๋ค์์ ์ํํ๋ฉด:
const dates = RRule.fromString(
"DTSTART;TZID=America/Denver:20181101T190000;\n"
+ "RRULE:FREQ=WEEKLY;BYDAY=MO,WE,TH;INTERVAL=1;COUNT=7"
).all()
dates.map((date) => date.toISOString())
์ผ๊ด๋๊ฒ ์ ํํ ๋ ์ง์ ์๊ฐ์ด ํฌํจ๋ ๊ฒฐ๊ณผ ISO ๋ฌธ์์ด์ ๋ณผ ์ ์์ต๋๋ค.
๋ํ Chrome์ UTC๋ก ๋ ์ง ๋ฐํ์ ์ ํ ์ง์ํ์ง ์๋ ๊ฒ์ผ๋ก ๋ณด์ ๋๋ค.
> new Date(Date.UTC(2016, 10, 5))
Fri Nov 04 2016 17:00:00 GMT-0700 (Pacific Daylight Time)
// ^ I asked for a date in UTC, not in PDT!
RRule์ Luxon์ ์ฌ์ฉํ์ฌ ํ์ง ์๊ฐ๋๋ฟ๋ง ์๋๋ผ _์ ์ธ๊ณ์ ๋ชจ๋ ์๊ฐ๋_์ ๋ํ ์ ํํ ํ์ง ์๊ฐ์ ์์ฑํฉ๋๋ค. ์ด๊ฒ์ด UTC ์ฌ์ฉ์ด ์ค์ํ ์ด์ ์
๋๋ค. ์๊ฐ๋ ์ฝ๋๊ฐ ํ์ง ์๊ฐ๋์ ๋ํด "์ฌ๋ฐ๋ฅธ" ๋ ์ง๋ฅผ ๋ฐํํ์ง๋ง ๋ค๋ฅธ ์๊ฐ๋( TZID
๋งค๊ฐ๋ณ์์ ํจ๊ป ์ ๊ณต๋จ)์์ ๋ ์ง๋ฅผ ์์ฑํด์ผ ํ๋ ๊ฒฝ์ฐ ๋ค์์ ์ป์ ์ ์์ต๋๋ค. ์์ฒญ๋๊ฒ ์๋ชป๋ ๊ฒฐ๊ณผ. ์ฐ๋ฆฌ๊ฐ "UTC ๋ ์ง"๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋ UTC๋ก DST ์ํ์ ํ๊ธฐ ๋๋ฌธ์ด ์๋๋ผ(ํ
์คํธ ์ค์ํธ๋ฅผ ๊ฒ์ฌํ๊ณ ์ฌ๋ฐ๋ฅธ DST ๊ณ์ฐ์ ๋ง์ ์๋ฅผ ๋ณผ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค) JavaScript ์ฌ์์ ์๊ฐ๋๊ฐ ๋์ฐํ๊ธฐ ๋๋ฌธ์
๋๋ค. ๊นจ์ง๊ณ UTC๋ ์ฌ์ฉ ๊ฐ๋ฅํ "์ค๋ฆฝ์ ์ธ" ๋ ์ง ๊ฐ๋
์ ๊ฐ์ฅ ๊ฐ๊น์ต๋๋ค. ์์
ํ๊ธฐ ํผ๋์ค๋ฝ๊ณ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ฌ์ฉ๋ฒ์ด ๋ ๋ช
ํํ์ง ์๋ค๋ ์ ์ ๋ํด ์ ๊ฐ์ค๋ฝ๊ฒ ์๊ฐํฉ๋๋ค(์ ์์ ์ด๋ ค ์์ต๋๋ค).
์ฐ๋ ค๋๋ ๊ฒ์ ๋ธ๋ผ์ฐ์ ํธํ์ฑ ๋ฌธ์ ์ ๋๋ค. ์ด์ ์คํ ์ค์ธ Node ์ฝ์์ด๋ Firefox์์ ๊ณ ์ ํ ์ํ ์ฝ๋๋ฅผ ์ฌ์ฉํด ๋ณด์๊ธฐ ๋ฐ๋๋๋ค. ๋งค์ฐ ๋ค๋ฅธ(๊ทธ๋ฆฌ๊ณ ์ ํํ) ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ฒ ๋ ๊ฒ์ ๋๋ค.
๋ฐ๋ผ์ ์ฌ๊ธฐ์ ์ค์ ๋ฌธ์ ๋ Chrome์์ ๊ฒฐ๊ณผ๊ฐ ํผ๋๋๋ค๋ ๊ฒ์ ๋๋ค. ์ ํํ ์ด๋ป๊ฒ ํด์ผ ํ๋์ง ๋น์ฅ์ ์ ์ ์์ง๋ง ์ธ๊ธํ ๊ฐ์น๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ด๊ฐ ๋งํ ์ ์๋ ๊ฒ์ ๋ ํ๊ฒฝ ๋ชจ๋ ์ ํํ ๋์ผํ ISO ๋ฌธ์์ด๊ณผ ํ์์คํฌํ๋ฅผ ์์ฑํ๋ค๋ ๊ฒ์ ๋๋ค.
@davidgoli ๋ง์ต๋๋ค. Firefox๋ ์๋ ์ฝ๋๋ฅผ ์คํํ ๋ ์ฝ์์ ๋ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ํ์ํฉ๋๋ค. ๊ทธ๋ฌ๋ ๊ฒฐ๊ณผ๋ ๊ถ๊ทน์ ์ผ๋ก ๋์ผํ ์๊ฐ์ด๋ฉฐ Firefox์์๋ ๊ฒฐ๊ณผ๊ฐ UTC ์๊ฐ์ผ๋ก ํ์๋๋ ๋ฐ๋ฉด Chrome์์๋ America/Denver
์๊ฐ(๋๋ ์๋ง๋ ํ์ง ์๊ฐ๋๊ฐ ๋ฌด์์ด๋ )์ผ๋ก ํ์๋ฉ๋๋ค.
๋๋ ๋น์ ์ ์ฃผ์ด์ง "์์"์ถ๋ ฅ์ด ์ ๋น์ ์ด ์ ๋ง๋ก ๊ธฐ๋ํ๋ ๊ฒ์ธ์ง ์ดํดํ ์ ์๋ค๊ณ ๋งํ๊ณ ์ถ์ต๋๋ค. ํด๋น ์๊ฐ์ด ์๋ชป ํ์๋ฉ๋๋ค.
์ฃผ์ด์ง ํ์ง ์๊ฐ์ ๊ฐ ์๊ฐ์ ๋ํ TZ ์คํ์ ์ ์ถ๊ฐํ๋ฉด ์ ํํ ์๊ฐ์ด ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ๋ชจ๋ ์๊ฐ์ 19:00์ด ๋ฉ๋๋ค. ์ด๊ฒ์ด RRule์ด UTC๋ฅผ ๋ค๋ฃจ๋ ์ด์ ์ด๋ฉฐ UTC์ ์ฌ์ฉ์ด ์ด ํน์ ๋ฒ๊ทธ์ ์๋ฌด ๊ด๋ จ์ด ์๋ ์ด์ ์ ๋๋ค.
๋ชจ๋ ๋ฐ๋ณต ์ด๋ฒคํธ์ ๋ํด 19:00 UTC ์๊ฐ์ ์ํ์ง ์๋ ์ด์ ๋ฅผ ์ค๋ช ํ๋ ค๊ณ ํฉ๋๋ค.
์ฌ์ฉ์๊ฐ ๋งค์ฃผ ์์์ผ ์คํ 1์์ America/Denver
์๊ฐ๋ ์ ํน์ ์์น์์ ๋ฐ๋ณต๋๋ ์ด๋ฒคํธ๋ฅผ ์์ฝํ๋ ค๊ณ ํ๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. ๊ฐ๋จํ ๋งํด์, ์ฐ์ค ์ธ์ ์ด๊ฑด ์๊ด์์ด ์ฌ์ฉ์๋ ๋งค์ฃผ ์์์ผ ์คํ 1์ ์ ํด๋น ์์น์์ ์์์ผ ์คํ 1์์ ๋์ผํ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๊ธฐ๋ฅผ ๊ธฐ๋ํฉ๋๋ค. 12์๋ ์๋๊ณ 2์๋ ์๋๊ณ ๋ฏธ๊ตญ/๋ด๋ฒ ์๊ฐ์ ๊ฒฝ์ฐ ํญ์ ์คํ 1์์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ rrule์ timezone์ ๋๊ฒจ๋ UTC ์๊ฐ์ ๋ฐ๋ผ ์ฌ๋ฐ์ ํด๊ฒฐํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก "์ค์ค์คํ 1์ America/Denver๋ 19:00 ์ผ๋ก ํ๊ฐํฉ๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ์ฌ์ค์ด ์๋๋๋ค. 2018๋ 11์ 4์ผ ์ด์ ์ ์ฌ์ค์ด์ง๋ง 11์ 4์ผ ์ดํ America/Denver๋ ์ผ๊ด ์ ์ฝ ์๊ฐ์ ๋ฅผ ํด์ ํฉ๋๋ค. ์ด ์์ ์์ UTC ์๊ฐ 19:00 ์ ์ด์ America/Denver ์๊ฐ 12:00pm์ผ๋ก ํ๊ฐ๋ฉ๋๋ค . ๋ฐ๋ผ์ ์ฌ์ฉ์๋ ์ด๋ฒคํธ๊ฐ ์คํ 1์๊ฐ ์๋๋ผ ์คํ 12์์ ๋ฐ์ํ๋ค๊ณ ์๋ชป ์๊ณ ์์ต๋๋ค.
์ฆ, 1pm America/Denver๋ ์ผ๊ด ์ ์ฝ ์๊ฐ์ ์ธ์ง ์ฌ๋ถ์ ๋ฐ๋ผ 19:00 ๋๋ 20:00 UTC๊ฐ ๋ ์ ์์ผ๋ฉฐ 19:00๋ผ๊ณ ๋งํ๊ณ ์ถ๊ธฐ ๋๋ฌธ์ ์ฌ๋ฐ๋ฅธ ๋ฐ๋ณต์ ์ป๊ธฐ ์ํด rrule์ ์ฌ์ฉํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค. 00์ ์ฐ์ค ๋ด๋ด ์ ํํ ์๊ฐ์ ๋๋ค.
๋๋ rrule์ด ๋๋ถ๋ถ์ ํ๋ก๊ทธ๋๋จธ๊ฐ ๋ฏฟ๋ ์ ํ, ์ฆ UTC๊ฐ ๋ ์ง์ ์๊ฐ์ ๋ค๋ฃฐ ๋ ํญ์ ์ฌ๋ฐ๋ฅธ ์๋ฃจ์ ์ด๋ผ๋ ์ ํ๋ฅผ ๋ฐ์๋ค์ด๊ณ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด๊ฒ์ด ์ต์ ์ ์๋ฃจ์ ์ด ์๋ ํน์ ๊ฒฝ์ฐ๊ฐ ์์ผ๋ฉฐ ์ด ๊ฒฝ์ฐ(ํน์ ์์น์์ ๋ฏธ๋์ ์ด๋ฒคํธ ๋ฐ๋ณต)๊ฐ ๊ทธ ์ค ํ๋์ ๋๋ค.
ํธ์ง: ์ด๋ก ์ ์ผ๋ก rrule์ด UTC๋ก ์๊ฐ์ ๋ฐํํ๋ ๊ฒ์ ๊ด์ฐฎ์ง๋ง, ํด๋น ์๊ฐ์ ์๊ฐ๋๊ฐ ์ ๋ฌ๋ ๋ ์ฃผ์ด์ง ์๊ฐ๋์ ๋ํด ์ ํํด์ผ ํฉ๋๋ค. ์ฆ, 19:00 UTC๊ฐ 20:00 UTC๋ก ์ ํ๋๋ ๊ฒ์ ๋ณผ ์ ์์ด์ผ ํฉ๋๋ค. ์ฌ๊ธฐ์์ ๋ ผ์๋๋ ์์ ๊ฒฝ์ฐ ๊ฒฐ๊ณผ ์งํฉ์ ํน์ ์ง์ .
์ฌ๊ธฐ๋ก ๋ฐฑ์ - ๋ฌธ์ํ ๋ฌธ์ ๋ผ๊ณ ์๊ฐํฉ๋๋ค.
RRule _always_๋ JS "UTC" ๋ ์ง๋ฅผ ๋ฐํํฉ๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๋ ๋ค๊ณ ํด์ ํด๋น ๋ ์ง๊ฐ UTC ์๊ฐ์ ๋ํ๋ด๋ ๊ฒ์ ์๋๋๋ค. ์คํ๋ ค, ์ ์ผํ ๋์์ธ ํ์ง ๋ ์ง์ ์ ํ์ผ๋ก ์ธํด ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ํํ๋ ๋ ์ง ๊ณ์ฐ์ ์๊ฐ๋ ์คํ์
์ด 0์ธ _only_ JS ๋ ์ง๋ฅผ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒฐ์ ์ด ๋ด๋ ค์ก์ต๋๋ค. ์ด๊ฒ์ ์ด๋ฌํ ์๊ฐ์ด ์ค์ ๋ก UTC์ ์๊ฐ์ ๋ํ๋ด๋ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง ์ค์ ๋ก๋ TZID
๋งค๊ฐ๋ณ์๋ก ํ์๋๋ ์๊ฐ๋์์ ํด์๋์ด์ผ ํ๋ค๋ ์๋ชป๋ ๋ถ์์ฉ์ด ์์ต๋๋ค. ์๋ฅผ ๋ค์ด Firefox์์ ์๋ํ ๋์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ 19:00์ ๋ํ๋ด๋ Date๋ฅผ ๋ฐํํ๊ณ ํด๋น ์๊ฐ์ Denver ์๊ฐ์ผ๋ก ์์ฒญํ๊ธฐ ๋๋ฌธ์ Denver ์๊ฐ์ ๋ง๋๋ก ํ๋ ๊ฒ์
๋๋ค. JavaScript์์ ์ ์ฉํ ์ ์ผํ ์ข
๋ฅ์ ๋ ์ง์ด๊ธฐ ๋๋ฌธ์ ์ด ๋ ์ง๊ฐ UTC ๋ ์ง๋ผ๊ณ ๋ณด๊ณ ํ๋ค๋ ์ฌ์ค์ ๋ฌด์ํด์ผ ํฉ๋๋ค. ๋์ ์ด ๊ท์น์ Denver ์๊ฐ๋๊ฐ ์๋ค๋ ์ง์์ ์ฌ์ฉํ์ฌ 19:00์ Denver์ ํ์ง ์๊ฐ์ผ๋ก ํด์ํด์ผ ํฉ๋๋ค.
์ด๊ฒ์ ๋ก์ปฌ ์์คํ
์์ญ ์ธ๋ถ์ ์๊ฐ๋๋ฅผ ์ฌ์ฉํ ๋ ๋ ๋ช
ํํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๋์ America/New_York
์์ญ ์ด๋ฆ์ผ๋ก RRule์ ์ค์ ํ๋ฉด ๋ ์ง๊ฐ 17:00์ผ๋ก ๋ฐํ๋๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค. ์ด๊ฒ์ 19์ผ ๋ ์ปดํจํฐ์ ์๊ฐ๋(Denver)์์ ํ์ง ์๊ฐ์ด๊ธฐ ๋๋ฌธ์
๋๋ค. :00 ์์ฒญํ ์๊ฐ๋(๋ด์).
JavaScript๋ ๋ ์ง๋ฅผ ํน์ ์๊ฐ๋์ "๊ณ ์ "ํ ๋ฐฉ๋ฒ์ด ์์ผ๋ฏ๋ก ์ด๋ค ๊ฒฝ์ฐ์๋ ํญ์ ์ ํํ ๋ ์ง์ ์๊ฐ์ ๋ํ๋ด๋ฏ๋ก Date๊ฐ ์์ฒด์ ์ผ๋ก UTC๋ก ๋ณด๊ณ ํ๋ค๋ ์ฌ์ค์ ๋ฌด์ํ ์ ์์ต๋๋ค. RRule์์ ์๊ฐ๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์ค์ ๋ก๋ ํ์ง ์๊ฐ์ ๋๋ค. ์ด๊ฒ์ด Firefox๊ฐ ์ ํํ ํ์ง ์๊ฐ์ 19:00์ผ๋ก ์ ๊ณตํ๋ ์ด์ ์ ๋๋ค(ํด๋น ๋ ์ง๊ฐ UTC๋ก ๋ณด๊ณ ๋์ง๋ง ์ค์ ๋ก๋ Denver ์๊ฐ์ ๋๋ค).
์ด๊ฒ์ด ๋ชจ๋ ๊ฒ์ ๋ช ํํ ํฉ๋๊น? ๋๋ ๊ทธ๊ฒ์ด ํผ๋์ค๋ฝ๊ณ ์ง๊ด์ ์ด์ง ์๋ค๋ ๊ฒ์ ์ดํดํ์ง๋ง, ์ผ๋จ ์ดํด๋๋ฉด ์ถ๋ก ํ๊ธฐ ์ฌ์์ง๋ค๋ ๊ฒ์ ์ดํดํ ๋งํผ ๊ฐ๋จํ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ์ฐ๋ฆฌ๋ ํ์คํ ์ด๊ฒ์ ๋ ์ ๋ฌธ์ํํด์ผ ํฉ๋๋ค.
์ด๊ฒ์์ ๋ด๊ฐ ํ๊ตฌํ๊ณ ์ถ์ ํ ๊ฐ์ง๋ Luxon์ ์ฌ์ฉํ์ฌ ๊ฒฐ๊ณผ ๋ ์ง๋ฅผ ํ์ง ์๊ฐ๋๋ก ์กฐ์ ํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ๋ฐ๋ผ์ ์ต์ํ ๊ทํ์ ๊ธฐ๋์ ์ผ์นํฉ๋๋ค. ๋๋ ์ด๊ฒ์ด ๋๋ฌด ์ด๋ ต์ง ์์์ผํ๋ฉฐ ์ด์ ๊ฐ์ ์คํด๋ฅผ ๋ช ํํํ๋ ๋ฐ ๋์์ด๋์ด์ผํ๋ค๊ณ ์๊ฐํฉ๋๋ค. Chrome ๋ฌธ์ ๋ ๋์๊ฒ ์ง์ ์ผ๋ก ์๋ก์ด ๊ฒ์ด๋ฉฐ ๋์ ์์์ ๋๋ค.
๊ทธ๋ฌ๋ ์ด๊ฒ์ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ด๋ฏ๋ก ๋ฐฐ์กํ๊ธฐ ์ ์ ์ปค๋ฎค๋ํฐ ํผ๋๋ฐฑ์ ์ํ ๊ธฐํ๋ฅผ ์ ๊ณตํ๊ณ ์ถ์ต๋๋ค.
@shorlbeck ์ด diff๋ ๋ค์๊ณผ ๊ฐ์ด ์์๋๋ ๋์์ ๊ตฌํํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
diff --git a/src/datewithzone.ts b/src/datewithzone.ts
index 8ae3ed0..d9b917c 100644
--- a/src/datewithzone.ts
+++ b/src/datewithzone.ts
@@ -38,7 +38,10 @@ export class DateWithZone {
const rezoned = datetime.setZone(this.tzid!, { keepLocalTime: true })
- return rezoned.toJSDate()
+ return rezoned
+ .toUTC()
+ .setZone('local', { keepLocalTime: true })
+ .toJSDate()
} catch (e) {
if (e instanceof TypeError) {
console.error('Using TZID without Luxon available is unsupported. Returned times are in UTC, not the requested time zone')
diff --git a/test/rrule.test.ts b/test/rrule.test.ts
index 7774b8a..a794e02 100644
--- a/test/rrule.test.ts
+++ b/test/rrule.test.ts
@@ -3804,4 +3804,17 @@ describe('RRule', function () {
expect(() => rule.between(invalidDate, validDate)).to.throw('Invalid date passed in to RRule.between')
expect(() => rule.between(validDate, invalidDate)).to.throw('Invalid date passed in to RRule.between')
})
+
+ it('#300', () => {
+ const rule = RRule.fromString(
+ "DTSTART;TZID=America/Denver:20181101T190000;\n"
+ + "RRULE:FREQ=WEEKLY;BYDAY=MO,WE,TH;INTERVAL=1;COUNT=3"
+ )
+
+ expect(rule.all()).to.deep.equal([
+ DateTime.utc(2018, 11, 2, 1, 0, 0).toJSDate(),
+ DateTime.utc(2018, 11, 6, 2, 0, 0).toJSDate(),
+ DateTime.utc(2018, 11, 8, 2, 0, 0).toJSDate(),
+ ])
+ })
})
๊ทธ๋ฌ๋ ์ด๊ฒ์ด ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ํ ๋ฐฉ๋ฒ์ด๋ผ๊ณ ์์ ํ ํ์ ํ ์๋ ์์ต๋๋ค. ํญ์ ํด๋ผ์ด์ธํธ์ ํ์ง ์๊ฐ๋์์ ํด์๋๋๋ก ์๋๋ "๋ถ๋" ์๊ฐ์ ๋ฐํํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ผ๋ฐ์ ์ธ ์ ๊ทผ ๋ฐฉ์์ด ์ ๊ณต๋ฉ๋๋ค(0 ์คํ์
์ด ์์์๋ ๋ถ๊ตฌํ๊ณ ). rrule
์์ ๋ฐํ๋ ๋ ์ง์ ๋ํ ์ ์ ํ getter๋ getUTC*
getter์ด๋ฏ๋ก ์๋ฅผ ๋ค์ด ์๋ ๊ฒฐ๊ณผ์ ๊ฐ ๋ ์ง์ getUTCHours()
๋ฅผ ์ฌ์ฉํ๋ฉด Chrome์์๋ ์ ํํ ์๊ฐ์ ํ์ธํ ์ ์์ต๋๋ค.
์ฌ๊ธฐ์ ์ฌ๋ฐ๋ฅธ ์์ ์ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋์์ ๋ณ๊ฒฝํ๋ ๊ฒ์ด ์๋๋ผ ์์ฌ "UTC"(์ค์ ๋ก๋ "ํ๋กํ ") ์๊ฐ์ ๋ค์ ํน์ดํ ์ฌ์ฉ๋ฒ์ ๋ ๋ช ํํ๊ฒ ๋ฌธ์ํํ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๋ ์ชฝ์ผ๋ก ๊ธฐ์ธ๊ณ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋๋ ์ด๊ฒ์ ๋ํด ์ค๋๋ ฅ์ด ์์ต๋๋ค.
๊ทํ์ ์ฌ์ฉ ์ฌ๋ก์ ๋ํ ๋ช ๊ฐ์ง ์ค๋ช ๊ณผ ์ง์นจ์ผ๋ก README๋ฅผ ์ ๋ฐ์ดํธํ์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด ๋ ผ์๋ฅผ ๊ณ์ํ๋ ๋ฐ ๊ด์ฌ์ด ์์ผ๋ฉฐ ํฅํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฒ์ ์์ ์ด ๋์์ ๋ณ๊ฒฝํ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค.
๋ต๋ณ๊ณผ ์์ธํ ์ค๋ช ๊ฐ์ฌํฉ๋๋ค.
๋ถํํ๋, ๋๋ ๊ฒฐ์ฝ ๋ ํผ๋์ค๋ฌ์ํ์ง ์์์ต๋๋ค.
๋ ์ง์ ์๊ฐ์ผ๋ก ์์ ํ๋ ๊ฒ์ ๋ ์ง ์๊ฐ์ด ์ค์ ๋ก UTC์ด๊ฑฐ๋ ์ค์ ๋ก ํ์ง ์๊ฐ์ผ ๋ ์ถฉ๋ถํ ์ด๋ ต์ง๋ง ๋๋๋ก UTC ์๊ฐ์ด ์ค์ ๋ก UTC ์๊ฐ์ด ์๋๋ผ๋ ๊ฒ์ ๊ธฐ์ตํด์ผ ํ๋ ๊ฒ์ ๋ด ๋๋๊ฐ ์ฒ๋ฆฌํ ์ ์๋ ๊ฒ ์ด์์ ๋๋ค. ๋๋ ์ค๋ ํ๋ฃจ ์ข ์ผ ๋น์ ์ด ์ด ๊ฒ์ ์ดํดํ๋ ค๊ณ ๋ ธ๋ ฅํ์ง๋ง ํ๋ฃจ๊ฐ ๋๋๋ฉด ์์ ํ ๋ฐ์ง๊ด์ ์ด์ด์ ๋ด ๋ง์์ ๊ฐ์ ์ ์์ต๋๋ค.
์ฝ๋๋ฅผ ๋ณผ ๋๋ง๋ค "UTC" ๋ ์ง๊ฐ ํ์๋ ๋๋ง๋ค ๊ทธ๊ฒ์ด ์ค์ ๋ก UTC ์ธ์ง ๊ทธ๋ฅ ์์ฌ UTC์ธ์ง ๊ธฐ์ตํ ์ ์์ต๋๋ค. ํนํ ๊ฑฐ๊ธฐ์ Chrome ๋ฌธ์ ๋ฅผ ์ถ๊ฐํ ๋ ๊ทธ๋ ์ต๋๋ค. ๊ทธ๊ฒ์ ๋ด๊ฐ ์ฝ๋ฉํ๋ ๊ฒ์ ๊ฑฐ์ ๋ถ๊ฐ๋ฅํ๊ฒ ๋ง๋ญ๋๋ค. ๊ทธ๊ฒ์ ๋ด ์ฝ๋์ ๊ฐ๋ ์ฑ์ ๋ํ ๋์ ์ ๋ขฐ๋ฅผ ๋ง์น๊ณ ์์ต๋๋ค.
์ฌ๊ธฐ ๋ด ์ง๋ฌธ์ด ์์ต๋๋ค. ๊ทธ๋ฌ๋ฉด... ์๋์ ์๋ก ๋์๊ฐ์... ์ค์ UTC์์ 2018-11-01 19:00:00
๋ ๋ฏธ๊ตญ/๋ด๋ฒ ์๊ฐ(13:00)์ ์คํ 1์๋ฅผ ๋ํ๋
๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ ์์์๋ ์คํ 1์ America/Denver๊ฐ ์ ์ด๋ฒคํธ์ ์ ํํ ์๊ฐ์
๋๋ค. ๊ทธ๋ฌ๋ UTC๊ฐ ์ค์ UTC๊ฐ ์๋ ๊ฒฝ์ฐ tzid
๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ ๋ new Date(Date.UTC(2018, 10, 1, 13, 0, 0))
๋๋ new Date(Date.UTC(2018, 10, 1, 19, 0, 0))
๋ฅผ ์ ๋ฌํด์ผ ํฉ๋๊น? (์ฐจ์ด๋ 13:00 vs. 19:00)
์์ฌ UTC๊ฐ ๋ค์ด์ค๊ณ ๋๊ฐ๋ ๊ฒ์ ๋๊น? ์๋๋ฉด ์ค์ UTC๊ฐ ๋ค์ด๊ฐ๊ณ ์์ฌ UTC๊ฐ ๋์ค๋์? ๊ทธ๋ฆฌ๊ณ ์ด๋ป๊ฒ ์ด๊ฒ์ ํ์คํ๊ฒ ๊ธฐ์ตํ ์ ์์ต๋๊น??
๊ท์น์ ๋ค์๊ณผ ๊ฐ์ด ์ง์ ๋ฉ๋๋ค.
DTSTART;TZID=America/Denver:20181101T190000
RRULE:FREQ=WEEKLY;BYDAY=MO,WE,TH;INTERVAL=1;COUNT=7
๊ทธ๋ฌ๋ RRULE RFC5545์ ๋ฐ๋ฅด๋ฉด ์ด๊ฒ์ ํ์ง ์๊ฐ์ด 1900์ธ Denver ์๊ฐ๋์ ๊ท์น์ ๋ํ๋ ๋๋ค. https://tools.ietf.org/html/rfc5545#section -3.3.5
For example, the following represents 2:00 A.M. in New York on January 19, 1998:
TZID=America/New_York:19980119T020000
1300 ํ์ง Denver ์๊ฐ์ DTSTART๋ฅผ ์ํ๋ฉด ๊ท์น์ 1300์ผ๋ก ์ง์ ํด์ผ ํฉ๋๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ด์ ๊ด๋ จํ์ฌ ์ฌ์์ ์ฒ ์ ํ ์ค์ํด์ผ ํฉ๋๋ค. (๊ธ์, 1300 UTC๋ฅผ ๋ฐํํ๋ค๋ ์ฌ์ํ ์ฌ์ค์ ์ ์ธํ๊ณ ...)
๋ํ "๋ถ๋ ์๊ฐ"์ ๋ํ ์น์ ์ ์ฝ์ผ์ญ์์ค.
FORM #1: DATE WITH LOCAL TIME
The date with local time form is simply a DATE-TIME value that
does not contain the UTC designator nor does it reference a time
zone. For example, the following represents January 18, 1998, at
11 PM:
19980118T230000
DATE-TIME values of this type are said to be "floating" and are
not bound to any time zone in particular. They are used to
represent the same hour, minute, and second value regardless of
which time zone is currently being observed. For example, an
event can be defined that indicates that an individual will be
busy from 11:00 AM to 1:00 PM every day, no matter which time zone
the person is in. In these cases, a local time can be specified.
JavaScript๋ ๋ถํํ๋ "๋ถ๋ ์๊ฐ"์ ๊ตฌํ์ ์ ๊ณตํ์ง ์์ต๋๋ค. "์์ํ" ์๊ฐ๋ ์๋ ์๊ฐ์ ๊ฐ์ฅ ๊ฐ๊น์ด ์ต์
์ UTC์ด๋ฏ๋ก "psuedo-UTC"์
๋๋ค. (์ฐธ๊ณ ๋ก rrule
๋ TZID๋ Z
UTC ์ง์ ์๋ก ์ง์ ๋์ง ์์ ๋ถ๋ ์๊ฐ๋ ์ง์ํฉ๋๋ค.)
UTC๋ก์ ์ ํ์ ๋ค์ ์ปค๋ฐ์ผ๋ก ์์ ํ ์์๋์์ต๋๋ค. https://github.com/jakubroztocil/rrule/commit/850ed075175eb1acfcbd7b2cddf0606f2b2206f7
์ด์ ์ปค๋ฐ์ ํ์ธํ๊ณ #850ed075์์ ์ถ๊ฐ๋ ํ
์คํธ๋ฅผ ์ ํํ๋ฉด ์คํจํ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค. ์ฌ์ค, ์ ์ฒด ์ ํ๊ตฐ์ด UTC๋ก ์คํ๋์ง ์๋ ํ ์๋ฐฑ ๊ฐ์ ํ
์คํธ๊ฐ ์คํจํ์ต๋๋ค. DST ๊ฒฝ๊ณ์ ๊ฑธ์ณ ์๋ ๋ฏธ๋ ๋ ์ง๋ฅผ ๊ณ์ฐํ๋ ค๋ฉด ํ์ฌ ์๊ณ๊ฐ DST์์ ์คํ ์ค์ผ ๋ ๋ ์ง๋ฅผ ์ธ์คํด์คํํ ๋ค์ ํ์ค ์๊ฐ์ผ๋ก ์ค์ ํ๋ ์ํ์ ๊ณ์ฐํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์๋ชป๋ 1์๊ฐ ์คํ์
์ด ๋ฐ์ํ์ต๋๋ค. ํ์ฌ ๊ตฌํ์ ํญ์ ์ ํํ ํ์ง ์๊ฐ์ ์ ๊ณตํฉ๋๋ค. ์ด์ ์ ์ฒด ํ
์คํธ ์ค์ํธ๋ ์ค์ ๋ก ๋ชจ๋ ๋ก์ปฌ ํ๊ฒฝ์์ ํต๊ณผํ ๊ฒ์ด๋ฉฐ, ์ ํํ ๋ ์ง/์๊ฐ์ ์ป์ผ๋ ค๋ฉด getUTCDate()
/ getUTCHour()
๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
ํฅํ ๋ฒ์ ์์ ์ด๋ฅผ ๋ณ๊ฒฝํ๋ ๋ฐฉ๋ฒ์ ์กฐ์ฌํ๊ณ ์์ง๋ง Luxon๊ณผ ๊ฐ์ ํ์ ํ์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฑํํ์ง ์๊ณ ๋ ๋ณ๊ฒฝ์ด ๊ฐ๋จํ์ง ์์ต๋๋ค.
๋ค์ ๋ฒ์ ์์๋ ํ์ง ์๊ฐ๋๋ก ํญ์ ์ ํํ ๋ ์ง๋ฅผ ๋ฐํํ๋๋ก ๋์์ ๋ณ๊ฒฝํ๊ณ ์ถ์ต๋๋ค. ์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
DTSTART;TZID=America/Denver:20181101T130000
๋ ๋ด๋ฒ์ ์๋ ๊ฒฝ์ฐ 1300-0700
(ํ์ค ์๊ฐ) ๋๋ UTC์ ์๋ ๊ฒฝ์ฐ 2000Z
์ธ ๋ ์ง๋ฅผ ๋ฐํํฉ๋๋ค.DTSTART=20181101T130000
๋ ๋ด๋ฒ์ ์์ผ๋ฉด 1300-0700
, UTC์ ์์ผ๋ฉด 1300Z
์
๋๋ค.DTSTART=20181101T130000Z
๋ ๋ด๋ฒ์ ์์ผ๋ฉด 0600-0700
, UTC์ ์์ผ๋ฉด 1300Z
์
๋๋ค.์ด๊ฒ์ด ๋น์ ์ด ๊ธฐ๋ํ๋ ํ๋์ ๋๊น?
ํ ๊ฐ์ง ํฐ ๋ฌธ์ ๋ ์ฃผ์ด์ง ๋ก์ปฌ JS ํ๊ฒฝ์ด ๋จ์ผ ์๊ฐ๋์ ๋ ์ง๋ง ๋ํ๋ผ ์ ์๋ค๋ ๊ฒ์
๋๋ค. ๋ฐ๋ผ์ new Date(...)
๋๋ new Date(Date.UTC(...))
๋ชจ๋ ํน์ ์๊ฐ๋(ํ์ฌ ์๊ฐ๋์ ๋ค๋ฅผ ์ ์์)์์ ๋ ์ง-์๊ฐ์ ๋ํ๋ด๋ ค๋ ๊ฒฝ์ฐ์๋ ์ ์ ํ์ง ์์ต๋๋ค.
๋ฐ๋ผ์ ๋ค์๊ณผ ๊ฐ์ ํ๋์ ์ทจํด์ผ ํฉ๋๋ค.
new RRule({
dtstart: new Date(2018, 10, 1, 10, 0, 0),
tzid: 'America/Denver'
})
๋ก์ปฌ ๋จธ์ ์ด America/Los_Angeles
์ ์๋ค๋ฉด? ์์ฑํ๋ ์๊ฐ๊ณผ ํด๋น ์๊ฐ์ ์ํ๋ ์๊ฐ๋ ์ฌ์ด์ 1์๊ฐ ์ฐจ์ด๋ฅผ ์ต์ํ ์ด๋ ์ ๋ ์๊ณ ์์ด์ผ ํฉ๋๋ค. ๋ฐ๋ผ์ ์ค์ 11์(Denver ์๊ฐ, ์์ฒญํ ์์ญ) ๋๋ ์ค์ 10์( ๋ก์ค์ค์ ค๋ ์ค ์๊ฐ, ์ถ๋ฐ์ง)? ๋๋ ๋น์ ์ด ๋ ์ค ํ๋์ ๋ํ ์ฌ๋ก๋ฅผ ๋ง๋ค ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
ํํ์ ์ผ๋ก Date
๊ฐ์ฒด๋ ์๊ฐ๋ ๋๋ ์คํ์
๊ฐ๋
์ด ์๋ UTC ๋ฐ๋ฆฌ์ด ๋จ์์ ํ์์คํฌํ๋ฅผ ๋ํ๋ธ๋ค๋ ์ ์์ ISO ๋ ์ง ๋ฌธ์์ด ๋ฐ DTSTART ๋ฌธ์์ด๊ณผ ๋ค๋ฆ
๋๋ค. ๋ฐ๋ผ์ ์ํ๋ ์๊ฐ์ ํ์์คํฌํ๋ฅผ _์ฌ๋ฐ๋ฅธ ์์ญ์์_ ํํํ๋ ๊ฒ์ด ๊ฐ์ฅ ํฉ๋ฆฌ์ ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ฆ, ๋ก์ค์ค์ ค๋ ์ค์ ์๊ณ ๋ด๋ฒ์ ์๊ฐ์ ๋ํ๋ด๋ ค๋ฉด ์๋ ๊ฐ์ผ๋ก ์ด๊ธฐํ๋ Date ๊ฐ์ฒด๋ฅผ ์ ๋ฌํด์ผ ํฉ๋๋ค. ์คํ์
์ด ์ ์ฉ๋์์ต๋๋ค(๋ฐ๋ผ์ ์์ ์๋ ๋ด๋ฒ์์ ์ค์ 11์๋ฅผ ๋ํ๋). ํ์ง๋ง ์ด๊ฒ์ ํผ๋์ค๋ฝ์ต๋๋ค. ๊ทธ ๋ค์ ๋ด์์ผ๋ก ์ฌํํ๊ณ ๊ฐ์ ์๊ฐ์ ๋ํ๋ด๋ ค๋ฉด new Date(2018, 10, 1, 13, 0, 0)
๋ฅผ ์์ฑํด์ผ ํ๊ธฐ ๋๋ฌธ์
๋๋ค!
์ง์ญ ๋ ์ง์ ์ ์ฒด ๊ฐ๋ ์ ์ฐฝ ๋ฐ์ผ๋ก ๋ฒ๋ฆฌ๋ ๊ฒ์ ์ฅ์ ์ ์ด๊ฒ์ ์ฒ๋ฆฌํ ํ์๊ฐ ์๋ค๋ ๊ฒ์ ๋๋ค. ํ์๋ ๋ ์ง์ ์๊ฐ์ ๋ณํ์ ์ํํ์ง ์๊ณ ๋ชจ๋ ์๊ฐ๋์ ํฌ์๋ ์ ์๋ ๋ถ๋ ์๊ฐ์ผ๋ก ์ฒ๋ฆฌ๋ ์ ์์ต๋๋ค.
๋ฌผ๋ก ์ด๊ฒ์ Chrome๊ณผ ๊ฐ์ ์์ง์ ๋์์ผ๋ก ์ธํด ๋ณต์กํฉ๋๋ค.
๋ชฉ์ ์ ์ํด ๋ค์์ ์ํํ์ฌ ์ํ๋ ๊ฐ์ ์ป์ ์ ์์ต๋๋ค.
rule.all().map(d => new Date(
d.getUTCFullYear(),
d.getUTCMonth(),
d.getUTCDate(),
d.getUTCHours(),
d.getUTCMinutes(),
d.getUTCMilliseconds()
))
๋๋ ํ์ฌ ์ด๊ฒ์ด ์ ์ ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ํ๋์ง ๊ฒฐ์ ํ๋ ค๊ณ ๋ ธ๋ ฅํ๊ณ ์์ต๋๋ค ...
๊ฐ์ฌํฉ๋๋ค! ๋น์ ์ ๋๋ต์ ๋๋ฅผ ์ํด ์ ๋ง ๋ช
ํํ์ต๋๋ค. ์ด์ ๋ชจ๋ ๊ฒ์ ์ดํดํ๋ ค๊ณ ํ๋ค๊ฐ ์ง์น๊ณ ์ง์ณค๋ ๊ฒ ๊ฐ์์. ์ด์ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ์ ์ ์์ต๋๋ค. tzid
๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ ๋ ์๋ชป๋ ์๊ฐ์ ์ง๋๊ณ ์์์ต๋๋ค.
๋ชฉ์ ์ ์ํด ๋ค์์ ์ํํ์ฌ ์ํ๋ ๊ฐ์ ์ป์ ์ ์์ต๋๋ค.
rule.all().map(d => new Date( d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCMilliseconds() ))
๋๋ ํ์ฌ ์ด๊ฒ์ด ์ ์ ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ํ๋์ง ๊ฒฐ์ ํ๋ ค๊ณ ๋ ธ๋ ฅํ๊ณ ์์ต๋๋ค ...
์ด๊ฒ์ ๋๋ฅผ ์ํด ์ผํ์ต๋๋ค! ์ ๋ง ๊ณ ๋ง์. rule.all()
๋ฐ rule.between()
์ ์ํด ๋ฐํ๋๋ ๊ฒ์ ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ์ด ์์ผ๋ฉด ์ข์ ๊ฒ์
๋๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๋ ๋ ๋ค๋ฅธ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ ๋์
ํ์ง ์์ง๋ง ์ฌ์ ํ ๊ธฐ๋ณธ์ ์ผ๋ก ์์ ๋์์ ์ป์ ์ ์์ต๋๋ค. ๋ด๊ฐ rrulestr()
๋๋ RRule.fromString()
๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ง๋ง ๋ฐํ๋๋ ๋ ์ง ์ ํ์ ์ง์ ํ๊ธฐ ์ํด ์ถ๊ฐ ์ธ์ ๋๋ ๋ฌด์ธ๊ฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ ๋ ์ด๋ฅผ ๋ฌ์ฑํ๋ ๋ฐฉ๋ฒ์ด ํ์คํ์ง ์์ต๋๊น?
์
๋ฐ์ดํธ: ์์ d.getUTCMilliseconds()
๋ d.getUTCSeconds()
๋ก ๋ณ๊ฒฝ๋์ด์ผ ํฉ๋๋ค.
๋ฐ๋ผ์ ๊ทํ์ ์๋ฃจ์ ์ ๋ด ์์คํ ์ ์๊ฐ๋๊ฐ ์์ฒญ๋ ์๊ฐ๋์ ๊ฐ์ ๋ ์๋ํ์ง๋ง ์์คํ ์๊ฐ๋์ ๋ค๋ฅผ ๋ RRule ์ด ์์ฒญํ ์๊ฐ๋ ์ ๋ ์ง๋ฅผ ๋ฐํํ๋๋ก ํ๋ ๋ฐฉ๋ฒ์ ์์๋ด๋ ค๊ณ ํ๋ ๋์ฐํ ์๊ฐ์ ๋ณด๋ด๊ณ ์์ต๋๋ค. ์์ฒญํ ์๊ฐ๋ ๋์ ์์คํ ์๊ฐ๋์ ํ์๋ ๋ ์ง๋ฅผ ํญ์ ๋ฐํํฉ๋๋ค. ์์:
America/Denver
๋ก ์ค์ ํฉ๋๋ค.RRule.fromString(
"DTSTART;TZID=America/Denver:20181101T130000;\n"
+ "RRULE:FREQ=WEEKLY;BYDAY=MO,WE,TH;INTERVAL=1;COUNT=7"
).all().map(d => new Date(
d.getUTCFullYear(),
d.getUTCMonth(),
d.getUTCDate(),
d.getUTCHours(),
d.getUTCMinutes(),
d.getUTCSeconds()
));
๊ฒฐ๊ณผ๊ฐ ์ ํํฉ๋๋ค(์์/ํ์ํ ๊ฒฝ์ฐ):
(7)ย [Thu Nov 01 2018 13:00:00 GMT-0600 (Mountain Daylight Time), Mon Nov 05 2018 13:00:00 GMT-0700 (Mountain Standard Time), Wed Nov 07 2018 13:00:00 GMT-0700 (Mountain Standard Time), Thu Nov 08 2018 13:00:00 GMT-0700 (Mountain Standard Time), Mon Nov 12 2018 13:00:00 GMT-0700 (Mountain Standard Time), Wed Nov 14 2018 13:00:00 GMT-0700 (Mountain Standard Time), Thu Nov 15 2018 13:00:00 GMT-0700 (Mountain Standard Time)]
America/New_York
๋ก ๋ณ๊ฒฝ๊ฒฐ๊ณผ๋ ์์คํ ์๊ฐ๋์ ํ์๋๊ธฐ ๋๋ฌธ์ ๋ค๋ฆ ๋๋ค.
(7)ย [Thu Nov 01 2018 15:00:00 GMT-0400 (Eastern Daylight Time), Mon Nov 05 2018 15:00:00 GMT-0500 (Eastern Standard Time), Wed Nov 07 2018 15:00:00 GMT-0500 (Eastern Standard Time), Thu Nov 08 2018 15:00:00 GMT-0500 (Eastern Standard Time), Mon Nov 12 2018 15:00:00 GMT-0500 (Eastern Standard Time), Wed Nov 14 2018 15:00:00 GMT-0500 (Eastern Standard Time), Thu Nov 15 2018 15:00:00 GMT-0500 (Eastern Standard Time)]
๊ทธ๋ฌ๋ ๊ฒฐ๊ณผ๊ฐ ๋ด ์์คํ
์๊ฐ๋๋ ์ค์ UTC๊ฐ ์๋ America/Denver
์๊ฐ์ ๋ํ๋ด๊ธฐ๋ฅผ ์ํฉ๋๋ค. America/Denver
๋ก ์ฌ์กฐ์ ํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํฉ๋๊น? ๋๋ Luxon์ ์ต์ํ์ง ์์ผ๋ฏ๋ก ๋์ moment()
๋ฅผ ์๋ํ์ต๋๋ค.
RRule.fromString(
"DTSTART;TZID=America/Denver:20181101T130000;\n"
+ "RRULE:FREQ=WEEKLY;BYDAY=MO,WE,TH;INTERVAL=1;COUNT=7"
).all().map(d => moment(new Date(
d.getUTCFullYear(),
d.getUTCMonth(),
d.getUTCDate(),
d.getUTCHours(),
d.getUTCMinutes(),
d.getUTCSeconds()
)).tz('America/Denver').toDate());
๊ทธ๋ฌ๋ toDate()
๋ ์ฆ์ ์์คํ
์๊ฐ๋(์ ์ด๋ Chrome์์๋)๋ก ๋๋๋ฆฌ๊ธฐ ๋๋ฌธ์ ๋ด์ ์๊ฐ์์ ๋์ผํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.
@shorlbeck MDT์ ๊ฒฐ๊ณผ์ EDT์ ๊ฒฐ๊ณผ๊ฐ ๋ชจ๋ UTC์์ ๋์ผํ๋ฏ๋ก ์ ์ง๋ฌธ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ๋ถ๋ ์๊ฐ์ด ์๋๋ผ TZID
๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์๊ฒ ์ต๋๊น? ์์คํ
์๊ฐ๋์ ๊ด๊ณ์์ด ํญ์ 13:00์ ์์ฑํ๋ ค๋ฉด ๋ถ๋ ์๊ฐ(๊ธฐ๋ณธ์ ์ผ๋ก ๋์ผํ์ง๋ง $#$ DSTART;TZID=<timezone>:<datetime>
DSTART:<datetime>
์ฌ์ฉ)์ ๊ถ์ฅํฉ๋๋ค.
13:00 ์ ์ฌ UTC์ ๋๋ค. Chrome ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ์ด์ ๋๊ธ์ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ฌ ๋ก์ปฌ ๋ ์ง๋ก ๋ณํํด์ผ ํฉ๋๋ค.
@davidgoli ์ค, ๋น์ ๋ง์ด ๋ง์์. ๋ถ๋ ์๊ฐ/์์ฌ UTC๊ฐ ์ค์ ๋ก ์๋ํ๋ ๋ฐฉ์์ ์ดํดํ ํ ์ค์ ๋ก tzid ๋งค๊ฐ๋ณ์๊ฐ ํ์ํ์ง ์๋ค๋ ๊ฒ์ ๊นจ๋ซ์ง ๋ชปํ์ต๋๋ค. ์ฆ, ์์ .map()
์๋ฃจ์
๋ ํ์ํ์ง ์์ต๋๋ค. ๊ทํ์ ์๊ฒฌ์ ์ฌ๋ฐ๋ฅธ ๋ฐฉํฅ์ผ๋ก ๋๋ฅผ ์ง์ ํ์ต๋๋ค. ์ ๋ง ๊ณ ๋ง์.
์ด๊ฒ์ด ๋ด๊ฐ ์ค๋ซ๋์ ์์ ํ ๊ฒ ์ค ๊ฐ์ฅ ํผ๋์ค๋ฌ์ด ์ผ์ด ์๋์๋ค๋ฉด ๊ฑฐ์ง๋ง์ด๊ฒ ์ง๋ง, ์ง๊ธ์ ์ฌ๋ฐ๋ฅธ ๋ฐฉํฅ์ผ๋ก ๊ฐ๊ณ ์์ด ๊ธฐ์ฉ๋๋ค.
ํ์ํ ๊ฒ์ ๋ช ์์ ์ผ๋ก ํํํ๋ ๊ฒ์ ๊ณ ๋ คํ์ต๋๊น(์๊ฐ๋ ์๋ ๋ถ๋ ๋ ์ง)? ๊ธฐ๋ณธ JS Date๋ฅผ UTC ์๊ฐ๋ ์ ํจ๊ป ์ฌ์ฉํ๊ณ ๋ฌธ์์์ UTC๋ผ๊ณ ์ฃผ์ฅํ๋ ๊ฒ์ DST ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ๋๊น์ง ์๋ํ๊ธฐ ๋๋ฌธ์ ๋งค์ฐ ํผ๋์ค๋ฝ์ต๋๋ค.
(year, month, day, hours?, minutes?, seconds?, milliseconds?)
์์ฑ์๋ฅผ ์ฌ์ฉํ๊ณ .toDate()
๋ฉ์๋๊ฐ ์๋ "RRuleDate"๋ผ๊ณ ํ๋ ๊ฐ์ฒด๋ฅผ ์ ์ํ๊ฒ ์ต๋๋ค.
์ด RRuleDate๋ before()
, after()
, between()
๋ฐ all()
๊ฐ ๋ฐํ๋์ด์ผ ํ๋ ํญ๋ชฉ์ด๋ฉฐ before()
, after()
, between()
๋ฐ dtstart
์ต์
์ ๋งค๊ฐ๋ณ์๋ก ํ์ฉ๋์ด์ผ ํฉ๋๋ค.