$30 off During Our Annual Pro Sale. View Details »

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

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
    TIME.. IS BUT AN
    ILLUSION
    IN JAVASCRIPT!
    @mybluewristband

    View Slide

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

    View Slide

  3. @mybluewristband
    Jennifer Wong Mode analytics Mozilla tech speaker whovian

    View Slide

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

    View Slide

  5. @mybluewristband
    @mybluewristband

    View Slide

  6. @mybluewristband
    QUE PASÓ?
    What happened?
    ?

    View Slide

  7. @mybluewristband
    RECURRING
    INVITES
    A past project
    @mybluewristband

    View Slide

  8. @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

    View Slide

  9. @mybluewristband
    @mybluewristband

    View Slide

  10. @mybluewristband
    @mybluewristband

    View Slide

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

    View Slide

  12. @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

    View Slide

  13. @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

    View Slide

  14. @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)

    View Slide


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

    View Slide


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

    View Slide

  17. @mybluewristband
    EL TIEMPO ES RARO
    Time is weird.
    @mybluewristband

    View Slide

  18. @mybluewristband
    @mybluewristband

    View Slide

  19. @mybluewristband
    EL TIEMPO
    Tale as old as time
    @mybluewristband

    View Slide

  20. @mybluewristband

    View Slide

  21. @mybluewristband

    View Slide

  22. @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

    View Slide

  23. @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)

    View Slide

  24. @mybluewristband
    G
    M
    T
    !!!
    @mybluewristband

    View Slide

  25. @mybluewristband
    JAVASCRIPT
    DATE
    OBJECT
    It's old

    View Slide

  26. @mybluewristband
    @mybluewristband

    View Slide

  27. @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()

    View Slide

  28. @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

    View Slide

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

    View Slide

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

    View Slide


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

    View Slide

  32. @mybluewristband
    @mybluewristband

    View Slide

  33. @mybluewristband
    TYPE COERCION
    One can coerce a date to a number of milliseconds from the Unix Epoch
    simply by using:

    +new Date()
    @mybluewristband

    View Slide

  34. @mybluewristband
    JAVASCRIPT
    VERSUS
    MOMENT.JS
    FIGHT!
    @mybluewristband

    View Slide

  35. @mybluewristband
    GETTERS
    Go get 'em

    View Slide

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

    View Slide

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

    View Slide

  38. @mybluewristband
    SETTERS
    Get, set, match (?)
    @mybluewristband

    View Slide

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

    View Slide

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

    View Slide

  41. @mybluewristband
    OTHER METHODS
    I've got gadgets and gizmos a-plenty
    @mybluewristband

    View Slide

  42. @mybluewristband

    View Slide

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

    View Slide

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

    View Slide

  45. @mybluewristband
    LOCALE
    STRINGS
    Whoa
    @mybluewristband

    View Slide

  46. @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()

    View 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

    View Slide

  48. @mybluewristband

    View Slide

  49. View Slide

  50. View Slide

  51. @mybluewristband

    View Slide

  52. @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()

    View Slide

  53. @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()

    View Slide

  54. @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()

    View Slide

  55. @mybluewristband
    MOMENT.JS
    A library!
    @mybluewristband

    View Slide

  56. @mybluewristband
    ENTONCES, POR
    QUE MOMENT?
    ?

    View Slide

  57. @mybluewristband

    View Slide

  58. @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

    View Slide

  59. @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

    View Slide

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

    View Slide

  61. @mybluewristband

    View Slide

  62. @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
    }

    View Slide

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

    View Slide

  64. @mybluewristband

    View Slide


  65. @mybluewristband
    Just use JavaScript until you can't
    anymore!
    Jennifer Wong

    View Slide

  66. @mybluewristband
    You’ll

    View Slide

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

    View Slide

  68. @mybluewristband

    View Slide

  69. @mybluewristband
    TEMPORAL
    A tc39 proposal

    View Slide

  70. @mybluewristband

    View Slide

  71. @mybluewristband

    View Slide

  72. @mybluewristband


    ❤❤❤❤❤

    View Slide

  73. @mybluewristband
    MAS COSAS

    View Slide

  74. @mybluewristband
    Zell Liew for CSS Tricks!

    View Slide

  75. View Slide

  76. @mybluewristband

    View Slide

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

    View Slide