Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Time is but an Illusion.. in JavaScript! (JSCon...

Jenn
October 18, 2019

Time is but an Illusion.. in JavaScript! (JSConf CO)

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.

Jenn

October 18, 2019
Tweet

More Decks by Jenn

Other Decks in Technology

Transcript

  1. @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
  2. @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
  3. @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
  4. @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)
  5. “ @mybluewristband Check the timezone of your CI server. Doubly

    so if it's running JavaScript tests. Jennifer Wong
  6. @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
  7. @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)
  8. @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()
  9. @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
  10. @mybluewristband TYPE COERCION One can coerce a date to a

    number of milliseconds from the Unix Epoch simply by using: +new Date() @mybluewristband
  11. // Date Object 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.js moment() moment().date() moment().day() moment().year() moment().hour() moment().millesecond() moment().minute() moment().month() moment().second() moment().get() moment().zone() // deprecated @mybluewristband
  12. // Date Object 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.js 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
  13. // Date Object 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.js moment().date() moment().year() moment().hour() moment().millesecond() moment().minute() moment().month() moment().second() moment().set() moment().year() @mybluewristband
  14. // Date Object Date.prototype.setUTCDate() Date.prototype.setUTCFullYear() Date.prototype.setUTCHours() Date.prototype.setUTCMilliseconds() Date.prototype.setUTCMinutes() Date.prototype.setUTCMonth() Date.prototype.setUTCSeconds()

    // Moment.js moment().utc().date() moment().utc().year() moment().utc().hour() moment().utc().milleseconds() moment().utc().minutes() moment().utc().month() moment().utc().seconds() @mybluewristband
  15. // Date Object Date.prototype.toDateString() Date.prototype.toISOString() Date.prototype.toJSON() Date.prototype.valueOf() // Returns milliseconds

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

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

    Date.prototype.toLocaleTimeString() // Moment.js moment().format('L') moment().format('L, LTS') moment().format(‘LTS') moment().locale()
  18. 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
  19. @mybluewristband DEPRECATED 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 Date.prototype.getYear() Date.prototype.setYear()
  20. @mybluewristband DEPRECATED 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 Date.prototype.toGMTString()
  21. @mybluewristband NON STANDARD 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+ Date.prototype.toLocaleFormat()
  22. @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
  23. @mybluewristband DATE TIME MATH IS EASY 1-2-3 moment().add() // Add

    to any part(s) of a date moment().subtract() // Subtract from any part(s) of a date moment().startOf() // Sets any part of a date to the beginning moment().endOf() // 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
  24. @mybluewristband Docs: https://momentjs.com/timezone/ Create moments with timezones Easily edit those

    timezones MOMENT TIMEZONE moment.tz() // Create a moment with a time zone or edit the timezone. moment.tz.Zone { name : 'America/Los_Angeles', // the unique identifier abbrs : ['PDT', 'PST'], // the abbreviations untils : [1414918800000, 1425808800000], // the timestamps in milliseconds offsets : [420, 480] // the offsets in minutes }
  25. @mybluewristband BUT DON’T TAKE MY ADVICE Do what's best for

    your team and your need to scale @mybluewristband