TIME.. IS BUT AN ILLUSION IN JAVASCRIPT! @mybluewristband

QUIEN ERES TU? ? @mybluewristband Who are you? @mybluewristband

Jennifer Wong 🕰 Mode analytics 🕰 Mozilla tech speaker 🕰 whovian @mybluewristband

DOCTOR WHO 🕠 Time Lord 🕠 Sonic Screwdriver 🕠 T.A.R.D.I.S 🕠 Daleks @mybluewristband

@mybluewristband

QUE PASÓ? What happened? @mybluewristband ?

RECURRING INVITES A past project @mybluewristband

RECURRING INVITES 🕠 Generate an recurrence rule (rrule) on the frontend (???) in iCal format 🕠 All existing rrule libraries were 1.5+ years out of date 🕠 But now there is an updated one: https://github.com/jakubroztocil/rrule 🕠 So I wrote my own rrule library… 🕠 Ensure timezone attached to rrule 🕠 Timezone of office location, not employee 🕠 Employees are based all over the world 🕠 May create invites for people in other offices @mybluewristband

@mybluewristband

@mybluewristband

FREQ=WEEKLY; BYDAY=FR; UNTIL=20190629T120000Z; @mybluewristband

RECURRING INVITES - A PROBLEM 🕠 We were in PST or GMT-7/GMT-8 (daylight savings) 🕠 All tests would pass locally 🕠 At 4pm/5pm PST/PDT, all frontend CI tests would fail for a few hours @mybluewristband

RECURRING INVITES - A PROBLEM 🕠 Some tests written with assuming a specific time zone (PST/PDT) 🕠 But the CI server was in a different timezone 😭 🕠 Tests didn’t expect that times minutes or hours apart might be in different days @mybluewristband

RECURRING INVITES - A SOLUTION KINDA 🕠 Local testing vs CI testing issues 🕠 Resolution: set a particular time/time zone in a test 🕠 But this only reliably tests that specific time/time zone 🕠 Also, undo any time mocking or the next test(s) will use the same time/time zone (and probably fail) @mybluewristband

“ Don’t write your own recurrence rule library. Doubly so for JavaScript. Jennifer Wong @mybluewristband

“ Check the timezone of your CI server. Doubly so if it’s running JavaScript tests. Jennifer Wong @mybluewristband

EL TIEMPO ES RARO Time is weird. @mybluewristband

@mybluewristband

EL TIEMPO Tale as old as time @mybluewristband

@mybluewristband

@mybluewristband

HISTORY OF TIME 🕠 https://en.wikipedia.org/wiki/Time 🕠 Artifacts from the Paleolithic suggest the moon was used to reckon time 🕠 Lunar calendars first appeared 🕠 🕠 Years of either 12 or 13 lunar months (354 or 384 days) 🕠 The earliest lunar calendar was discovered in 8000 BC. Egyptians created the first of several time measurement devices 🕠 T-square 🕠 Sundial 🕠 Water clock @mybluewristband

TYPES OF TIME ZONES OR STANDARDS 🕠 Greenwich Mean Time (GMT) 🕠 🕠 🕠 Created in 1847 at the Royal Observatory in Greenwich Universal Coordinated Time (UTC) 🕠 International Meridian Conference (of 26 nations) 🕠 $ Colombia was there! 🤝 🕠 & The United States was there! 🤝 Unix Time 🕠 Number of seconds that have passed since the Unix Epoch 🕠 🕠 00:00:00 UTC Thursday, 1 January 1970 International Standards Organization (ISO) @mybluewristband

G M T !!! @mybluewristband

JAVASCRIPT DATE OBJECT It’s old @mybluewristband

@mybluewristband

ECMA-262 🕠 JavaScript! 🕠 Version 1 - 1997 🕠 Only six new Date object methods have been added since then Date.prototype.toDateString() Date.prototype.toISOString() Date.prototype.toJSON() Date.prototype.toLocaleDateString() Date.prototype.toLocaleTimeString() Date.prototype.toTimeString() @mybluewristband

WHY THE 0 INDEX 🕠 JavaScript’s Date object has a zero indexed month 🕠 java.util.Date had 0-indexed month 🕠 java.time package was released in 2014 with a 1-indexed month 🕠 Moment.js uses a zero indexed month @mybluewristband

https://stackoverflow.com/questions/2552483/why-does-the-month-argument-range-from-0-to-11-injavascripts-date-constructor/41992352#41992352 @mybluewristband

https://stackoverflow.com/questions/2552483/why-does-the-month-argument-range-from-0-to-11-injavascripts-date-constructor/41992352#41992352 @mybluewristband

“ Because Java. Brendan Eich (creator of JavaScript) @mybluewristband

@mybluewristband

TYPE COERCION 😬😬😬 One can coerce a date to a number of milliseconds from the Unix Epoch simply by using: +new Date() @mybluewristband

JAVASCRIPT VERSUS MOMENT.JS FIGHT! @mybluewristband

GETTERS Go get ‘em @mybluewristband

// Date Object // Moment.js Date.prototype.constructor Date.prototype.getDate() Date.prototype.getDay() Date.prototype.getFullYear() Date.prototype.getHours() Date.prototype.getMilliseconds() Date.prototype.getMinutes() Date.prototype.getMonth() Date.prototype.getSeconds() Date.prototype.getTime() Date.prototype.getTimezoneOffset() moment() moment().date() moment().day() moment().year() moment().hour() moment().millesecond() moment().minute() moment().month() moment().second() moment().get() moment().zone() // deprecated @mybluewristband

// Date Object // Moment.js Date.prototype.getUTCDate() Date.prototype.getUTCDay() Date.prototype.getUTCFullYear() Date.prototype.getUTCHours() Date.prototype.getUTCMilliseconds() Date.prototype.getUTCMinutes() Date.prototype.getUTCMonth() Date.prototype.getUTCSeconds() moment().utc().date() moment().utc().day() moment().utc().year() moment().utc().hour() moment().utc().milleseconds() moment().utc().minutes() moment().utc().month() moment().utc().seconds() @mybluewristband

SETTERS Get, set, match (?) @mybluewristband

// Date Object // Moment.js Date.prototype.setDate() Date.prototype.setFullYear() Date.prototype.setHours() Date.prototype.setMilliseconds() Date.prototype.setMinutes() Date.prototype.setMonth() Date.prototype.setSeconds() Date.prototype.setTime() Date.prototype.setYear() // deprecated moment().date() moment().year() moment().hour() moment().millesecond() moment().minute() moment().month() moment().second() moment().set() moment().year() @mybluewristband

// Date Object // Moment.js Date.prototype.setUTCDate() Date.prototype.setUTCFullYear() Date.prototype.setUTCHours() Date.prototype.setUTCMilliseconds() Date.prototype.setUTCMinutes() Date.prototype.setUTCMonth() Date.prototype.setUTCSeconds() moment().utc().date() moment().utc().year() moment().utc().hour() moment().utc().milleseconds() moment().utc().minutes() moment().utc().month() moment().utc().seconds() @mybluewristband

OTHER METHODS I’ve got gadgets and gizmos a-plenty @mybluewristband

@mybluewristband

// Date Object // Moment.js Date.prototype.toDateString() moment().format(‘ddd MMM DD YYYY’) Date.prototype.toISOString() Date.prototype.toJSON() moment().utc().format(‘YYYY-MM-DDTHH:mm:ss.SSS’) + ‘Z’ moment().utc().format(‘YYYY-MM-DDTHH:mm:ss.SSS’) + ‘Z’ Date.prototype.valueOf() parseInt( moment().format(‘x’), 10 ) // Returns milliseconds since // the Unix epoch which is // 1 January 1970 00:00:00 UTC // Returns the string version of milliseconds since // Unix epoch then parses into an integer @mybluewristband

// Date Object // Moment.js Date.prototype.toString() // e.g. Thu Oct 10 2019 22:46:02 // GMT-0700 (Pacific Daylight Time) moment().toDate().toString() // Translate into a Date object // then run .toString() on it Date.prototype.toTimeString() // e.g. 22:46:02 GMT-0700 // (Pacific Daylight Time) moment().toDate().toTimeString() // Translate into a Date object // then run .toString() on it Date.prototype.toUTCString() // e.g. Fri, 11 Oct 2019 // 05:46:02 GMT moment().utc().format( ‘ddd, DD MMM YYYY HH:mm:ss’ ) + ’ GMT’ @mybluewristband

LOCALE STRINGS Whoa @mybluewristband

LOCALE STRINGS // Date Object Date.prototype.toLocaleDateString() Date.prototype.toLocaleString() Date.prototype.toLocaleTimeString() // Moment.js moment().format(‘L’) moment().format(‘L, LTS’) moment().format(‘LTS’) Super cool! moment().locale() @mybluewristband

var event = new Date(Date.UTC(2012, 11, 20, 3, 0, 0)); var options = { weekday: ‘long’, year: ‘numeric’, month: ‘long’, day: ‘numeric’ }; console.log(event.toLocaleDateString(‘de-DE’, options)); // expected output: Donnerstag, 20. Dezember 2012 console.log(event.toLocaleDateString(‘ar-EG’, options)); // expected output: ٢٠١٢ ،‫ دﯾﺴﻤﺒﺮ‬٢٠ ،‫اﻟﺨﻤﯿﺲ‬ console.log(event.toLocaleDateString(‘ko-KR’, options)); // expected output: 2012년 12월 20일 목요일 @mybluewristband

@mybluewristband

@mybluewristband

DEPRECATED Date.prototype.getYear() Date.prototype.setYear() 🕠 Returned a two digit OR four digit year 🕠 People didn’t think we’d live beyond the Mayan calendar 🕠 https://developer.mozilla.org/en-US/ docs/Web/JavaScript/Reference/ Global_Objects/Date/getYear @mybluewristband

DEPRECATED Date.prototype.toGMTString() 🕠 Converts a date to a string, using Internet Greenwich Mean Time (GMT) conventions 🕠 Exact format of the return value varies according to the platform and browser… 🕠 https://developer.mozilla.org/en-US/ docs/Web/JavaScript/Reference/ Global_Objects/Date/toGMTString @mybluewristband

NON STANDARD Date.prototype.toLocaleFormat() 🕠 Converts a date to a string using the specified formatting 🕠 Does not use Intl.DateTimeFormat 🕠 🕠 Intl.DateTimeFormat formats dates in a standards-compliant way Deprecated as of Firefox 58+ @mybluewristband

MOMENT.JS A library! @mybluewristband

ENTONCES, POR QUE MOMENT? @mybluewristband ?

@mybluewristband

MORE GETTERS MOMENT.JS OFFERS moment().quarter() // Returns the year’s quarter moment().weekday() // Returns locale aware day of week moment().week() // Returns the week of the year moment().dayOfYear() // Returns the number day of the year from 1-366 moment().weeksInYear() // Returns the number of weeks in a specific year moment().unix() // Unix time in seconds @mybluewristband

DATE TIME MATH IS EASY 1-2-3 moment().add() moment().subtract() // Add to any part(s) of a date // Subtract from any part(s) of a date moment().startOf() moment().endOf() // Sets any part of a date to the beginning // Sets any part of a date to the end moment().local() // Set time to the local time zone moment().utc() // Set time to the equivalent UTC time zone moment().utcOffset() // Returns the UTC offset in minutes @mybluewristband

OMG TIMEZONES ⚠ ⚠ ⚠ ⚠ ⚠ $ vs & @mybluewristband

@mybluewristband

MOMENT TIMEZONE 🕠 Docs: https://momentjs.com/timezone/ 🕠 Create moments with timezones 🕠 Easily edit those timezones moment.tz() // Create a moment with a time zone or edit the timezone. moment.tz.Zone { name abbrs untils offsets : : : : ‘America/Los_Angeles’, [‘PDT’, ‘PST’], [1414918800000, 1425808800000], [420, 480] // // // // the the the the unique identifier abbreviations timestamps in milliseconds offsets in minutes } @mybluewristband

ENTONCES … ¿QUAL DEBEMOS USAR? Oh no se.. @mybluewristband

@mybluewristband

“ Just use JavaScript until you can’t anymore! Jennifer Wong @mybluewristband

You’ll @mybluewristband

BUT DON’T TAKE MY ADVICE Do what’s best for your team and your need to scale @mybluewristband

@mybluewristband

TEMPORAL A tc39 proposal @mybluewristband

@mybluewristband

@mybluewristband

😍😍😍😍😍 💙💙💙💙💙 ❤❤❤❤❤ @mybluewristband

MAS COSAS @mybluewristband

Zell Liew for CSS Tricks! @mybluewristband

@mybluewristband

¡MUCHAS GRACIAS! ¿Preguntas? Jennifer Wong @mybluewristband https://github.com/jennz0r @mybluewristband