Time is But an Illusion… in JavaScript!

A presentation at JSConf Colombia in October 2019 in Medellin, Antioquia, Colombia by Jennifer Wong

Slide 1

Slide 1

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

Slide 2

Slide 2

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

Slide 3

Slide 3

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

Slide 4

Slide 4

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

Slide 5

Slide 5

@mybluewristband

Slide 6

Slide 6

QUE PASÓ? What happened? @mybluewristband ?

Slide 7

Slide 7

RECURRING INVITES A past project @mybluewristband

Slide 8

Slide 8

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

Slide 9

Slide 9

@mybluewristband

Slide 10

Slide 10

@mybluewristband

Slide 11

Slide 11

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

Slide 12

Slide 12

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

Slide 13

Slide 13

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

Slide 14

Slide 14

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

Slide 15

Slide 15

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

Slide 16

Slide 16

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

Slide 17

Slide 17

EL TIEMPO ES RARO Time is weird. @mybluewristband

Slide 18

Slide 18

@mybluewristband

Slide 19

Slide 19

EL TIEMPO Tale as old as time @mybluewristband

Slide 20

Slide 20

@mybluewristband

Slide 21

Slide 21

@mybluewristband

Slide 22

Slide 22

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

Slide 23

Slide 23

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

Slide 24

Slide 24

G M T !!! @mybluewristband

Slide 25

Slide 25

JAVASCRIPT DATE OBJECT It’s old @mybluewristband

Slide 26

Slide 26

@mybluewristband

Slide 27

Slide 27

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

Slide 28

Slide 28

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

Slide 29

Slide 29

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

Slide 30

Slide 30

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

Slide 31

Slide 31

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

Slide 32

Slide 32

@mybluewristband

Slide 33

Slide 33

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

Slide 34

Slide 34

JAVASCRIPT VERSUS MOMENT.JS FIGHT! @mybluewristband

Slide 35

Slide 35

GETTERS Go get ‘em @mybluewristband

Slide 36

Slide 36

// 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

Slide 37

Slide 37

// 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

Slide 38

Slide 38

SETTERS Get, set, match (?) @mybluewristband

Slide 39

Slide 39

// 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

Slide 40

Slide 40

// 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

Slide 41

Slide 41

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

Slide 42

Slide 42

@mybluewristband

Slide 43

Slide 43

// 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

Slide 44

Slide 44

// 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

Slide 45

Slide 45

LOCALE STRINGS Whoa @mybluewristband

Slide 46

Slide 46

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

Slide 47

Slide 47

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

Slide 48

Slide 48

@mybluewristband

Slide 49

Slide 49

Slide 50

Slide 50

Slide 51

Slide 51

@mybluewristband

Slide 52

Slide 52

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

Slide 53

Slide 53

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

Slide 54

Slide 54

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

Slide 55

Slide 55

MOMENT.JS A library! @mybluewristband

Slide 56

Slide 56

ENTONCES, POR QUE MOMENT? @mybluewristband ?

Slide 57

Slide 57

@mybluewristband

Slide 58

Slide 58

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

Slide 59

Slide 59

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

Slide 60

Slide 60

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

Slide 61

Slide 61

@mybluewristband

Slide 62

Slide 62

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

Slide 63

Slide 63

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

Slide 64

Slide 64

@mybluewristband

Slide 65

Slide 65

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

Slide 66

Slide 66

You’ll @mybluewristband

Slide 67

Slide 67

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

Slide 68

Slide 68

@mybluewristband

Slide 69

Slide 69

TEMPORAL A tc39 proposal @mybluewristband

Slide 70

Slide 70

@mybluewristband

Slide 71

Slide 71

@mybluewristband

Slide 72

Slide 72

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

Slide 73

Slide 73

MAS COSAS @mybluewristband

Slide 74

Slide 74

Zell Liew for CSS Tricks! @mybluewristband

Slide 75

Slide 75

Slide 76

Slide 76

@mybluewristband

Slide 77

Slide 77

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