Date, time and timezone notes ¶
Client side ¶
Client side representation of shift date/time is handled with momentjs.
Shift objects are delivered with a ‘timezone’ string along with a string representation of the time/date.
Process ¶
Vet portal shifts are all loaded via ShiftMixin::getShiftsRange, which loads shifts from an api call then passes the raw shift data to ShiftMixin::processLoadedShifts.
This iterates over the list and runs ShiftMixin::processNewShift on each shift, which processes each shift in to a structure for the vuex store.
ShiftMixin::processNewShift calls ShiftMixin::parseFullTimeToMoment on the shift.start_time and shift.end_time with the shift.timezone, and returns a momentjs object. This happens for each shift pulled back in the api request, which typically involves a few hundred shifts per pull.
Problem uncovered ¶
primary problem with the moment object creation was uncovered in early sep 2021.
incorrect ¶
moment(timestring).tz(shift.timezone)
correct ¶
moment.tz(timestring, timezone)
The second version creates the appropriate representation in moment. This allows for displayinh “1pm” as “1pm”, regardless of a browser/os host timezone. The earlier usage didn’t, although it’s syntactically valid.
Changes ¶
- ShiftTime component was modified to show the shift’s timezone, primarily for debugging at this stage.
- moment object creation instances were corrected with the appropriate syntax. this was only required in small number of places in the code.
- Existing JS tests were modified - sample shifts were given a default Eastern timezone, and the default moment was given a default timezone as well.
- Site detail screen was modified to allow changing of timezone - all shifts created after the timezone change will inherit the site’s changed timezone.
- Site setup data was changed so that ‘Whiskers’ site is Chicago (Central) time.
- Added ‘EDT/CST’-style description on vet portal time card, and in the ‘schedule-overlay’ after the time.
Examples ¶
const a1 = moment.tz('2022-02-08 17:00:00','America/New_York');
const a2 = moment.tz('2022-02-08 15:00:00','America/Chicago');
a2.diff(a1, 'seconds');
-3600
const a = moment.tz('2021-09-08 17:00:00','America/New_York');
const b = moment.tz('2021-09-08 16:00:00','America/Chicago');
b.isBefore(a);
false
b.isAfter(a);
false
b.isSame(a);
true
DST fallback example ¶
let time1 = moment.tz('2021-11-07 01:59','America/New_York')
let time2 = time1.clone()
time2.add(1,'minute')
'1:00am'
time1.format('h:mma z')
'1:59am EDT'
time2.format('h:mma z')
'1:00am EST'
time1.diff(time2, 'seconds')
-60
time1.add(1,'minute')
time1.diff(time2, 'seconds')
0
time1.isSame(time2)
true
DST spring forward example ¶
let time1 = moment.tz('2022-03-13 01:59','America/New_York')
time1.format('h:mma z');
'1:59am EST'
let time2 = time1.clone()
time2.format('h:mma z');
'1:59am EST'
time1.diff(time2, 'seconds')
0
time2.add(1,'minute')
time1.diff(time2, 'seconds')
-60
time2.format('h:mma z');
'3:00am EDT'
momentjs deprecation ¶
In late 2020, the momentjs project, for a number of reasons, announced it was ceasing development. Current code will continue to work, but future development, patches, improvements would not happen. There are other in development libraries, and Luxon is a recommendation from the momentjs team. Luxon is intended as a close approximation of moment, with a big difference being that Luxon objects are immutable (removing the need to .clone() dates). We should investigate replacing moment with Luxon, but the initial ‘timezone’ support shift work is probably not the time to do this work.
Sep 16, 2021 ¶
$user->preferences is loaded during middleware on authenticated user window.app.configs has ‘core.hq_timzone’ and ‘core.timezones’ array (from Timezone::$timezones option class) This is in support of CATS-487 - making the user timezone and option available everywhere. The ‘vet portal profile’ work is not using this yet - still using data from AccountController but we can migrate that later.