A presentation at JSConf Colombia in in Medellin, Antioquia, Colombia by Jennifer Wong
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
With so much to worry about timing wise: formatting, time zones, internationalization, recurrence rules, leap years, daylight savings time, and more, everyone needs HELP!
Let’s turn time into money by taking a look at the most popular time libraries and how we use them to solve JavaScript’s time problems. We’ll look at how JavaScript’s Date object started and what its prototype allows. We’ll wind our way through dates, times, and standards to find solutions to the weirdness.
Let’s kill time together talking about JavaScript time! Because we know, time heals all.
Here’s what was said about this presentation on social media.
Day 1 of @jsconfco closes with an entertaining talk about time, Date and moment.js by @mybluewristband pic.twitter.com/0e8to5qn3n
— Luis Alejandro Vega (@luisalejovega) October 18, 2019
Amazing performance @mybluewristband with her Time talk... Effectively, it is an illusion 😄 Thank you very much pic.twitter.com/uTK9jaAPLG
— JuanGuillermo Rivera (@guillerivera325) October 18, 2019
And this is how we close the first day of #JSConfCO2019 @mybluewristband talking about the most popular time libraries and how we use them to solve JavaScript’s time problems. pic.twitter.com/EqzCA22VCk
— JSConf Colombia (@jsconfco) October 18, 2019
Jennifer Wong @mybluewristband discussed the weirdness of time handling in JavaScript, the history of the Date object and momentjs. And timezones too, of course! @jsconfco pic.twitter.com/zKUmWG1xyP
— Slashie (@slashie_) October 18, 2019
Timey wimey talk by fellow whovian @mybluewristband at @jsconfco 🔥💫🕜 pic.twitter.com/wyMhxaE1Fc
— Kevin Hernández 🐍 (@keeevinh) October 18, 2019
Is about time! @jsconfco Time for @mybluewristband pic.twitter.com/1K3Z8uCKwk
— Gerson Goatache (@Gerson4G) October 18, 2019
@mybluewristband is presenting now! #jsconfCO pic.twitter.com/UdT1P59ylF
— Ready Player Juan 🎮 (@juantorostuff) October 18, 2019
OMG! @mybluewristband is talking about Doctor Who at @jsconfco 😍 pic.twitter.com/XLFh64ZkSz
— Co 💚 (@co_constanza) October 18, 2019
You had me at "whovian" @mybluewristband #jsconfco #jsconf #JSConfCO2019 pic.twitter.com/qPjqQHdNrC
— The Fricky! (@the_fricky) October 18, 2019
😍 Welcome to my town Jennifer
— Calypso Brontë 🏳️🌈🦄 ◬ #ILA2019 #PlatziConf (@calypsobronte) October 18, 2019
" Time is but an illusion... in #javascript@mybluewristband @jsconfco #JSConfCO2019 #JSConfCO #js #jsconf pic.twitter.com/qFJALlS5I2