From 042140512369c4a24d9f7dfc113be6555d57f0fc Mon Sep 17 00:00:00 2001 From: Damian Krzeminski Date: Thu, 18 Apr 2024 11:24:52 +0200 Subject: [PATCH] add TZID property to date-time if available it's not clear if that actually leads to a better user experience than floating time that we are currently using Google Calendar seems to work OK with floating time - it is using the event location to properly display the time if the default timezone of the calendar is different from that of the event if we do set TZID Google Calendar will also use it, but it might make incorrect assumptions about DST (for example America/New York tends to result in Eastern Time - and not EDT or EST depending on the specific date) --- .jshintrc | 2 +- lib/ical.js | 11 ++++++--- test/fixtures/simple-trip.json | 20 +++++++++++++---- test/fixtures/simple_tz.ics | 41 ++++++++++++++++++++++++++++++++++ test/ical.js | 8 +++++++ 5 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 test/fixtures/simple_tz.ics diff --git a/.jshintrc b/.jshintrc index 9bf58ac..4a2f904 100644 --- a/.jshintrc +++ b/.jshintrc @@ -10,5 +10,5 @@ "sub": true, "undef": true, "unused": true, - "esversion": 10 + "esversion": 11 } diff --git a/lib/ical.js b/lib/ical.js index 3a06285..950d718 100644 --- a/lib/ical.js +++ b/lib/ical.js @@ -20,7 +20,11 @@ function ts2date(ts) { return new Date(ts).toISOString().replace(/[-:]/g, '').slice(0, -5); } -function* ical({ metadata, routes }) { +function tzid(property, tz) { + return tz ? `${property};TZID=${tz}` : property; +} + +function* ical({ metadata, routes, options = {} }) { const dtstamp = ts2date(Date.now()); yield* property('BEGIN', 'VCALENDAR'); @@ -41,8 +45,9 @@ function* ical({ metadata, routes }) { yield* property('URL', step.url); yield* property('LOCATION', step.address); yield* property('GEO', [step.coordinates.lat, step.coordinates.lon], formatArray); - yield* property('DTSTART', ts2date(step.arrival_time)); - yield* property('DTEND', ts2date(step.departure_time)); + const tz = options.tzid && step.timezone?.name; + yield* property(tzid('DTSTART', tz), ts2date(step.arrival_time)); + yield* property(tzid('DTEND', tz), ts2date(step.departure_time)); yield* property('END', 'VEVENT'); } yield* property('END', 'VCALENDAR'); diff --git a/test/fixtures/simple-trip.json b/test/fixtures/simple-trip.json index 564db58..377294d 100644 --- a/test/fixtures/simple-trip.json +++ b/test/fixtures/simple-trip.json @@ -34,7 +34,10 @@ "visit_duration": 0, "nights": 0, "arrival_time": 1373274000000, - "departure_time": 1373274000000 + "departure_time": 1373274000000, + "timezone": { + "name": "America/Los_Angeles" + } }, { "id": "5144f7cbd6e4d26079000009", @@ -58,7 +61,10 @@ "driving": 11580, "nights": 0, "arrival_time": 1373285580000, - "departure_time": 1373286480000 + "departure_time": 1373286480000, + "timezone": { + "name": "America/Los_Angeles" + } }, { "id": "5144f7dfd6e4d2607900000a", @@ -84,6 +90,9 @@ "nights": 0, "arrival_time": 1373304660000, "departure_time": 1373305560000, + "timezone": { + "name": "America/Los_Angeles" + }, "symbol": "Gas Station" }, { @@ -108,10 +117,13 @@ "driving": 6595, "nights": 0, "arrival_time": 1373312155000, - "departure_time": 1373312155000 + "departure_time": 1373312155000, + "timezone": { + "name": "America/Los_Angeles" + } } ], "name": "" } ] -} \ No newline at end of file +} diff --git a/test/fixtures/simple_tz.ics b/test/fixtures/simple_tz.ics new file mode 100644 index 0000000..7305c3e --- /dev/null +++ b/test/fixtures/simple_tz.ics @@ -0,0 +1,41 @@ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//code42day//Furkot - road trip planner//EN +BEGIN:VEVENT +DTSTAMP:20220529T071758 +UID:50d1b16d-3cc5-501a-9ab1-fa68286a011f@furkot.com +SUMMARY:San Francisco +LOCATION:San Francisco\, CA +GEO:37.7749295;-122.41941550000001 +DTSTART;TZID=America/Los_Angeles:20130708T090000 +DTEND;TZID=America/Los_Angeles:20130708T090000 +END:VEVENT +BEGIN:VEVENT +DTSTAMP:20220529T071758 +UID:d2a184cf-7264-570f-9880-003054b10222@furkot.com +SUMMARY:Redding +LOCATION:1510 Gordon Lane\, Redding\, CA 96002\, USA +GEO:40.54720023441049;-122.34375 +DTSTART;TZID=America/Los_Angeles:20130708T121300 +DTEND;TZID=America/Los_Angeles:20130708T122800 +END:VEVENT +BEGIN:VEVENT +DTSTAMP:20220529T071758 +UID:b66792fd-6bd2-5c84-91e7-27c6cd532a54@furkot.com +SUMMARY:Lane +LOCATION:51-559 Walnut Place\, Springfield\, OR 97477\, USA +GEO:44.04811573082351;-123.046875 +DTSTART;TZID=America/Los_Angeles:20130708T173100 +DTEND;TZID=America/Los_Angeles:20130708T174600 +END:VEVENT +BEGIN:VEVENT +DTSTAMP:20220529T071758 +UID:924fc5db-ab1d-5406-8a50-af6943d1c2f1@furkot.com +SUMMARY:Portland +DESCRIPTION:Trip notes for first stop +LOCATION:Portland\, OR +GEO:45.5234515;-122.6762071 +DTSTART;TZID=America/Los_Angeles:20130708T193555 +DTEND;TZID=America/Los_Angeles:20130708T193555 +END:VEVENT +END:VCALENDAR diff --git a/test/ical.js b/test/ical.js index 0c87913..0b6aef3 100644 --- a/test/ical.js +++ b/test/ical.js @@ -45,6 +45,14 @@ describe('ical', function () { compareLines(generated, expected); }); + it('simple trip with TZID', function () { + const t = require('./fixtures/simple-trip.json'); + const generated = ical({ ...t, options: { tzid: true } }); + const expected = readFileSync('fixtures/simple_tz.ics'); + + compareLines(generated, expected); + }); + it('multi trip', function () { const t = require('./fixtures/multi-trip.json'); const generated = ical(t);