A place to cache linked articles (think custom and personal wayback machine)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4 年之前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. title: UTC is Enough for Everyone, Right?
  2. url: https://zachholman.com/talk/utc-is-enough-for-everyone-right
  3. hash_url: 891e30df4c8c42238cf372bfe50dc266
  4. <div class="pa6-l pa3">
  5. <div class="w-60-l">
  6. <h2 id="since-the-dawn-of-time">Since the dawn of time</h2>
  7. <p>Years ago, I worked with a friend who had built a few scheduling calendars in a previous freelancing gig.</p>
  8. <p>Sometimes we’d be working on something that tangentially related to time, and as kind of a recurring in-joke he’d always tell me:</p>
  9. <blockquote class="mv4 bg-white black pv4 b--pink bw3 f4">
  10. Zach, whatever you do: just don't <em>ever</em> build a calendar.
  11. </blockquote>
  12. <p>Anyway, I’m Zach Holman and I’m <a href="http://during.com">building a calendar</a>.</p>
  13. <p>I guess I never could follow directions very well.</p>
  14. <p>Building a calendar sucks. Like there’s really cool shit you can do, since every calendar out there today is basically straight outta 2005, but at the end of the day you’re stuck dealing with all of the edge cases that all your dork friends have warned you about since the dawn of time. (Like literally, <em>the dawn of time</em> is a separate edge case you have to account for as well.) So there’s been a lot of heinous stuff we’ve had to work with.</p>
  15. </div>
  16. <div class="flex-l items-start">
  17. <div class="w-60-l">
  18. <p>I’ve made notes of the egregious things I’ve learned about programming with time and pulled them together as a talk. This is the written companion piece, which is sort of a super set of the talk, since I had way more notes than what I could shove in a single talk.</p>
  19. <p>Beyond that, though, there’s also a lot about time itself that is properly hilarious, and it’d be a travesty to not talk about the country that recently decided to skip a certain day, or that the Unix epoch isn’t technically the number of seconds since January 1970, or that February 30 happened at least twice in history.</p>
  20. <p>It turns out humans have had a long, long history of poorly dealing with time, so when you hammer your head against the wall trying to deal with a timezone bug, well, you’re just the last in a long, long line of human beings that are terrible at all this! Congrats. You’re pretty unremarkable.</p>
  21. </div>
  22. <div class="w-40-l mt4 ml4-l bg-white black f6 pa3 br1 lh-copy flex">
  23. <div class="flex-column">
  24. <i class="fal mr3 fa-2x">lightbulb</i>
  25. </div>
  26. <div class="flex-column">
  27. <p class="ma0">I've given this talk three times: at <a href="https://www.youtube.com/watch?v=aEvB98CstOk">RubyConfIndia</a>, RubyConf Australia, and Balkan Ruby. (Don't worry, non-Rubyists; there's no Ruby in this post. The conference topics were just happenstance. Also I love the word "happenstance".)</p>
  28. <p>Each of those talks were filmed, and I'll link to each of them above once the recording's been made available, in case you're more of a watch-and-listen kind of person.</p>
  29. </div>
  30. </div>
  31. </div>
  32. </div>
  33. <div class="video">
  34. <video class="z-1" src="/video/utc-one.mp4" poster="/images/talks/utc/poster-one.jpg" width="100%" preload="" autoplay="" loop="" muted="" playsinline=""></video>
  35. <div class="absolute top-0 white z-2 w-50 mt2 ml5 o-80">
  36. <h1 class="lh-solid">
  37. <div class="bg-yellow black dib tracked-tight avenir tc" style="width: 30vw; font-size: 4vw">What is</div>
  38. <div class="" style="font-size: 12vw">Time?</div>
  39. </h1>
  40. </div>
  41. </div>
  42. <div class="pa6-l pa3 intro">
  43. <div class="w-60-l">
  44. <h2 id="what-is-time">What is time?</h2>
  45. <p>What <em>is</em> time? Well, that’s a question as old as… time.</p>
  46. </div>
  47. <div class="flex-l items-start">
  48. <div class="w-60-l">
  49. <p>But yeah, basically time is like, just a social construct, mannnnnnnnnn. 🌱💨 Physicists are <a href="https://www.quantamagazine.org/a-debate-over-the-physics-of-time-20160719/">still debating on whether or not time actually exists</a> in the universe. This quickly gets us into the territory of asking ourselves really weird things that hurts our brain, like what is time, or what is physics, or if you only eat one donut from Krispy Kreme, did you even actually go there?</p>
  50. <p>So to avoid all of this, I’m just going to say that no, time doesn’t exist, therefor writing code for it doesn’t matter, so boom, we’re done here! Thanks for reading.</p>
  51. <p>Okay you’re not getting out of this that easy. But I think it is worthwhile to take a quick look at the history of time so we can figure out why it’s so goddamn hard to do things with timestamps.</p>
  52. </div>
  53. <div class="w-40-l mt4 ml4-l bg-black white f6 pa3 br1 lh-copy flex">
  54. <div class="flex-column">
  55. <i class="fal mr3 fa-2x">lightbulb</i>
  56. </div>
  57. <div class="flex-column">
  58. <p class="ma0">This stuff gets wild to read more about, in the existential <em>what-even-is-anything-anyway?</em> category of questions in life.</p>
  59. <p>Apparently <a href="https://www.sciencealert.com/physicists-find-as-clocks-get-more-precise-time-gets-more-fuzzy">time gets more fuzzy</a> as clocks get more and more accurate.</p>
  60. <p>Pretty sure this confirms we're living in a simulation, and the programmers were too lazy to fully flesh the code out before they reached their ship deadline.</p>
  61. </div>
  62. </div>
  63. </div>
  64. <div class="w-60-l mt6">
  65. <h2 id="a-brief-timeline-of-time">A brief timeline of time</h2>
  66. <ol class="timeline">
  67. <li>
  68. <span class="bg-black white pa3">4000+ BC</span> Astronomical clocks
  69. <div>We start seeing a bunch of "clocks" pop up. But like, they were shitty clocks: basically they'd be like the equivalent of looking up, seeing a sun, and like boom, I guess it's daytime.</div>
  70. </li>
  71. <li>
  72. <span class="bg-black white pa3">1500 BC</span> Sundial subdivisions
  73. <div>
  74. <p>Oh rad, now we start getting some nifty stuff. We start seeing more sundials split up into subdivisions, so we can be more specific about how far through the day we are.</p>
  75. <p>Egypt was the first ones to really start doing this: they had a duodecimal system already, so that's why it was split as base twelve, or our two parts of twelve hours in a day.</p>
  76. <p>If you're like me and immediately said <em>ohhhhhhhhhhhh, so THAT'S why there's twelve hours in a day!</em> and immediately followed it up with: <em>wait, why the fuck are they using twelve instead of ten? Base ten is lit and doing everything in twelve feels so uncivilized</em>, well good use of "lit" there.</p>
  77. <p>It's most likely because <a href="https://www.scientificamerican.com/article/experts-time-division-days-hours-minutes/">you have twelve joints in your hands</a>: three in each of the four fingers, excluding the thumb. I thought that was pretty nifty to discover. Like, I had never looked at my hands before, really. Hands are really wild, when you think about it. 🌱💨</p>
  78. </div>
  79. </li>
  80. <li>
  81. <span class="bg-black white pa3">14th century</span> Fixed-length hours
  82. <div>
  83. <p>European clocks started standardizing on fixed-length hours; before, a lot of clocks would change the duration of an hour depending on the season.</p>
  84. <p>Basically anything with time that seems weird like this can probably be summed up with "the goddamn farmers did it", since, you know, growing seasons were really important to figure out when you couldn't just walk down the block and go to a Taco Bell Cantina® for a Baja Blast™.</p>
  85. </div>
  86. </li>
  87. <li>
  88. <span class="bg-black white pa3">16th century</span> Minutes
  89. <div>
  90. <p>Wasn't until around the 16th century before we started seeing minutes. Before then, nobody really cared, and mechanical clocks weren't good enough to count 'em accurately, anyway.</p>
  91. <p>Probably around this time your first boss's ancestors were also discovering minutes as a good way to make sure your ancestors got to work on time: "You're exactly 56 minutes late today, Holman, what the fuck is wrong with you? Go shave the sheep!"</p>
  92. </div>
  93. </li>
  94. <li>
  95. <span class="bg-black white pa3">17th century</span> Seconds
  96. <div>
  97. <p>Did you hear about the clock maker who was the first to add a second hand to a clock?</p>
  98. <p>His first prototype was a complete failure, but he got it working the second time.</p>
  99. </div>
  100. </li>
  101. <li>
  102. <span class="bg-black white pa3">1883</span> USA standardizes time
  103. <div>
  104. <p>We start seeing some actual standardization on time itself.</p>
  105. <p>In what is the most bourgeoisie example of the most bourgeoisie era, a bunch of rich, white railroad tycoons met at a fancy Chicago hotel to agree on a standard timezone so their trains would work better together. They used the new-fangled telegraph to synchronize time signals between cities.</p>
  106. <p>Other countries would do the same thing around this era. Previously, it was basically a free for all as to what time it would be in any given city:</p>
  107. <blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Lamenting over timezone programming led me to this 1857 chart, and suddenly timezones seem GREAT. (At noon in DC, it was 12:08 in Philly!) <a href="https://t.co/mSYyUKL6lX">pic.twitter.com/mSYyUKL6lX</a></p>&mdash; Tess Rinearson (@_tessr) <a href="https://twitter.com/_tessr/status/900870734238449664?ref_src=twsrc%5Etfw">August 25, 2017</a></blockquote> <script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
  108. <p>So, consider yourself playing in easy mode today. You can't <em>imagine</em> how much harder it would be to be a JavaScript programmer in 1882.</p>
  109. </div>
  110. </li>
  111. <li>
  112. <span class="bg-black white pa3">1967</span> Atomic standard
  113. <div>
  114. <p>The world started standardizing on what time measurements actually <em>are</em>.</p>
  115. <p>If you have a pile of Cesium atoms sitting in your backyard, go out sometime and measure <a href="https://www.nist.gov/pml/walk-through-time-atomic-age-time-standards">9,192,631,770 energy transitions of a single atom of Cesium</a>: because that is exactly the duration of a second, settled upon in 1967 by a bunch of scientists.</p>
  116. <p>Nowadays, our atomic clocks are accurate to losing a single second over the course of a few hundred million years. This is something like only losing two nanoseconds of accuracy a month, which definitely accounts for why I'm always late to your meetings on Monday morning.</p>
  117. <p>The clocks being worked on today, though, are even better: optical clocks "tick" about a hundred thousand times faster than atomic clocks, which can lead to way higher accuracy. Basically if you somehow started one of these bad boys right at the Big Bang about 14 billion years ago and somehow kept it going, it would have <a href="https://physicsworld.com/a/new-optical-clock-breaks-accuracy-record/">only lost a few seconds of accuracy</a>.</p>
  118. </div>
  119. </li>
  120. <li>
  121. <span class="bg-black white pa3">2018</span> You fuck up yet another timezone bug
  122. <div>
  123. You didn't think I'd forget about you, did you?
  124. </div>
  125. </li>
  126. </ol>
  127. </div>
  128. </div>
  129. <div class="intro">
  130. <div class="white tc f3">
  131. <span class="fal fa-spin fa-pulse mh3">clock</span>
  132. <span class="fal fa-spin mh3">hourglass-start</span>
  133. <span class="fal fa-spin fa-pulse mh3">watch</span>
  134. <span class="fal fa-spin mh3">alarm-clock</span>
  135. <span class="fal fa-spin fa-pulse mh3">stopwatch</span>
  136. </div>
  137. </div>
  138. <div class="pa6-l pa3 intro">
  139. <div class="flex-l">
  140. <div class="w-60-l">
  141. <p>Everything we just covered revolves around a single question:</p>
  142. <h2 id="what-time-is-it">What time is it?</h2>
  143. <p>At a certain point we started asking this question. This became important to know when you could finally head home after work, for example (answer: never early enough). And for a long time that was fine, but that wasn’t <em>entirely</em> the question we were asking. There was a hidden implicit part of the question we were never asking:</p>
  144. <p><span class="ml3"><strong>What time is it <em>here</em>?</strong></span></p>
  145. <p>Once we started getting planes and trains and automobiles, we had movement, we had transportation, we could be in two distant places within hours. So we started asking this question:</p>
  146. <p><span class="ml3"><strong>What time is it <em>there</em>?</strong></span></p>
  147. <p>This question ruined everything.</p>
  148. <p>Now we had to deal not just with one time (here), not two times (here and there), but a multitude of times, all interacting with each other (everywhere). This complicated everything, and made obvious the notion that writing timezone code was some of the worst things you have to do in our field.</p>
  149. <p>It’s so predictable that developers will pooh-pooh having to write timezone code, almost as much as it is predictable that some clueless commenter on Hacker News will complain that this page has autoplaying video on it. And then someone will calmly quote this passage in response, quietly pleased with themselves that the initial commenter was rude and certainly didn’t read the post at all. Then a third person will chime in on the thread saying the author was playing you all like a fiddle anyway, and the real problem is that the post was way too long to start with.</p>
  150. </div>
  151. <div class="pa5 mv4 w-40-l">
  152. <a href="https://en.wikipedia.org/wiki/File:Universal_Dial_Plate_or_Times_of_all_Nations,_1854.jpg" class="no-slide"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d8/Universal_Dial_Plate_or_Times_of_all_Nations%2C_1854.jpg/757px-Universal_Dial_Plate_or_Times_of_all_Nations%2C_1854.jpg" /></a>
  153. <em class="f6">This is terrifying. It's a <a href="https://en.wikipedia.org/wiki/File:Universal_Dial_Plate_or_Times_of_all_Nations,_1854.jpg">"Universal Dial Plate"</a>, showing times of individual cities of the world, from 1854. Gulp.</em>
  154. </div>
  155. </div>
  156. <div class="mt5 w-60-l">
  157. <h2 id="timezones">Timezones</h2>
  158. <p>So you’re starting out fresh, building a completely new global time structure.</p>
  159. <p>Clearly, since you’re a programmer, you already have an innate distrust of timezones, so you’re going to get rid of them entirely, a la <a href="https://en.wikipedia.org/wiki/Swatch_Internet_Time">Swatch Internet Time</a>, which demonstrates why you are the beautiful human you are, you dashing human you.</p>
  160. <p>In fact, the title of this post is wrong: UTC isn’t enough for everyone; you should get rid of UTC and move all your servers to use Swatch Internet Time instead.</p>
  161. <p>Okay, now that we got that tomfoolery out of the way, we start asking questions about what time should look like. And if we do have timezones, the obvious thing to you is to split the world up into twenty four timezones, one for each hour in the day, so it’s all very neat and orderly.</p>
  162. <p>Spoiler alert! Nothing is neat and orderly when it comes to time. There’s something like 39 timezones at time of writing.</p>
  163. <p>This, like all of the problems with time, is political. Timezones get added gradually, over time, depending on political whims, geographical reality, and economic plausibility (more on a lot of these later). So, as a common theme you’ll see, this is just one example where we try to graft an irregular system (time and timezones) over a regular system (the duration from time point A to time point B).</p>
  164. <p>This stuff moves a lot, too: the <a href="https://en.wikipedia.org/wiki/Tz_database">tz database</a> (also known as the Olson database), which is the listing of timezone rules we use as programmers to calm this chaos, gets updated many times a year.</p>
  165. <p>It’s also worthwhile to point out here that timezones aren’t tied to hours: many timezone offsets happen at 30 minutes, 45 minutes, and so on. So we need to stop thinking purely about “hours” and start thinking about offsets, in a way.</p>
  166. <p>Timezones are weird. Time is weird.</p>
  167. </div>
  168. </div>
  169. <div class="video">
  170. <video class="z-1" src="/video/utc-two.mp4" poster="/images/talks/utc/poster-two.jpg" width="100%" preload="" autoplay="" loop="" muted="" playsinline=""></video>
  171. <div class="absolute top-0 white z-2 w-100 mt2 o-80">
  172. <h1 class="lh-solid">
  173. <div class="white dib tracked-tight avenir" style="margin-left: 30%; font-size: 4vw">Why</div>
  174. <div class="georgia i" style="font-size: 12vw; margin-left: 30%">Time</div>
  175. <div class="dib bg-blue black dib f1 tracked tc ph4" style="font-size: 5vw; margin-left: 35%">is so hard</div>
  176. </h1>
  177. </div>
  178. </div>
  179. <div class="pa6-l pa3 bg-blue blue">
  180. <div class="w-60-l">
  181. <h2 id="who-needs-december-30-2011-anyway">Who needs December 30, 2011 anyway</h2>
  182. <p>Let me tell you a quick story.</p>
  183. <p>Do you remember what you were doing on December 30, 2011? You have three seconds. Go.</p>
  184. <p>Nope? Nothing? Well then, if you don’t know what you were doing December 30, 2011, then there’s one obvious explanation for this: <strong>you must be Samoan</strong>.</p>
  185. <p>You see, Samoa didn’t have December 30, 2011. They went straight from December 29 to December 31, do not pass Go, do not collect $200.</p>
  186. <div class="shadow-1 mv4">
  187. <video class="db" src="/video/utc-samoa.mp4" poster="/images/talks/utc/poster-samoa.jpg" width="100%" preload="" autoplay="" loop="" muted="" playsinline=""></video>
  188. </div>
  189. <p>Samoa used to be east of the International Date Line. I mean, it still is (they didn’t physically move the country, which would be a pretty impressive feat, now that I think of it), but it used to actually follow the date line accordingly. In the years before 2011, Samoa looked up and realized that hey, most of our major trading partners — China, Australia, New Zealand, and the like — are on the <em>other</em> side of the date line, so when we’re dutifully working away at the office on Friday, the rest of the people we actually do business with have already fucked off for the weekend. The Kiwis are probably off grilling meat somewhere, never to be heard from until Monday, if we’re <em>lucky</em> to hear from them ever again at all.</p>
  190. <p>So Samoa decided to change timezones so that they could line up better economically.</p>
  191. <p>It’s also important to note that Samoa is about 100km away from American Samoa. Not super far at all.</p>
  192. <p><img src="/images/talks/utc/samoa-american-samoa.png" alt="Samoa and American Samoa map" /></p>
  193. <p>So at this point in my talk I say the next part <em>real fast</em>, so like, just read it real fast and we’ll try to approximate me. It’s best if you do a pile of cocaine before reading the next part. I’ll wait.</p>
  194. <p>Okay, so:</p>
  195. <div class="f5 ph4">
  196. <p>At the start, Samoa and American Samoa were in the same timezone, the <em>Samoa Time Zone</em>, which encompasses the two different countries, except it’s actually one country and one unincorporated territory of the United States (American Samoa), so when Samoa pulled out of this time zone it switched to the <em>West Samoa Time Zone</em> which was UTC +12:00 compared to <em>Samoa Time Zone</em> which stayed at UTC -11:00 which meant West Samoa Time Zone was 24 hours ahead of Samoa Time Zone which isn’t entirely accurate because sometimes it would be 25 hours ahead of Samoa Time Zone because Samoa Time Zone doesn’t observe Daylight Saving Time and, of course, West Samoa Time Zone also doesn’t observe Daylight Saving Time except it <em>does</em> observe it starting in 2009, wait that’s not true they had to push that back to 2010 because of the Samoa Earthquake and Tsunami which messed everything up; now naturally all of this may sound familiar to you because this is the mirror reverse of what happened on July 4, 1892 when the <em>opposite</em> happened when they looked around and said hey our major trading partner is the United States, why are we in a totally different day than these Yanks, so let’s do July 4, 1892 twice (which is doubly awesome and hella <em>🇺🇸 🎆 P A T R I O T I C 🎇 🗽</em>, since it’s Independence Day in the USA); it’s also important to note that Tokelau, a nearby territory of New Zealand, saw all this happening so they got in on the action and did the same thing and moved to West Samoa Time also on December 30, 2011.</p>
  197. </div>
  198. <p>When all of this happened, <a href="http://www.bbc.co.uk/news/mobile/world-asia-16351377">the BBC sent a journalist to Samoa</a> to see how they were taking it:</p>
  199. <blockquote>
  200. <p>You can hear the sound of a lot of vehicles going round town, going round the town centre clock and tooting their horns. People screaming.</p>
  201. <p>“We have once again achieved another milestone in our history of Samoa.”</p>
  202. </blockquote>
  203. <p>I don’t know who they interviewed for this piece, but what I do know is whoever said this thing never had to fucking deal with fucking timezone exceptions in code before. Fuck.</p>
  204. <p>Working with time is hard. There can be little edge cases like this every step of the way.</p>
  205. </div>
  206. </div>
  207. <div class="bg-blue">
  208. <div class="white tc f3">
  209. <span class="fal fa-spin fa-pulse mh3">clock</span>
  210. <span class="fal fa-spin mh3">hourglass-start</span>
  211. <span class="fal fa-spin fa-pulse mh3">watch</span>
  212. <span class="fal fa-spin mh3">alarm-clock</span>
  213. <span class="fal fa-spin fa-pulse mh3">stopwatch</span>
  214. </div>
  215. </div>
  216. <div class="pa6-l pa3 bg-blue blue">
  217. <div class="w-60-l">
  218. <h2 id="no-russian">No Russian</h2>
  219. <p>The Russian Olympic shooting team, pleased to represent their country on <em>The Big Stage</em>, was proud to head to London for the Games in 1908. They hit the road… <a href="https://www.reddit.com/r/todayilearned/comments/6ltsnz/til_in_1908_the_russian_olympic_team_arrived_at/?st=J4UA4D2H&amp;sh=fe9e2e7a">and made it to London twelve days too late</a> and missed their event.</p>
  220. <p>Turns out, in 1918, Russia switched to the Gregorian calendar. This was neat, because that moved yet another country to using Gregorian, so we could all be on the same page.</p>
  221. <p>In 1908, though, they were still on the Julian calendar. England, the host of the Olympics, was on the Gregorian calendar. So when they told them to show up at a certain date, the two calendars didn’t match up. Whoops.</p>
  222. <p>This mix-up was a bummer, but possibly not too unfamiliar for Russia, as the same thing happened in 1805 during the <a href="https://en.wikipedia.org/wiki/Battle_of_Austerlitz">Battle of Austerlitz</a>. Napoleon was doing his thing and invading Austria, and the Austrians, assured that Russian reinforcements would show up, you know, in time, was sad to also discover the woes of different calendars as reinforcements showed up twelve days too late. Napoleon ended up winning.</p>
  223. </div>
  224. </div>
  225. <div class="bg-blue">
  226. <div class="white tc f3">
  227. <span class="fal fa-spin fa-pulse mh3">clock</span>
  228. <span class="fal fa-spin mh3">hourglass-start</span>
  229. <span class="fal fa-spin fa-pulse mh3">watch</span>
  230. <span class="fal fa-spin mh3">alarm-clock</span>
  231. <span class="fal fa-spin fa-pulse mh3">stopwatch</span>
  232. </div>
  233. </div>
  234. <div class="pa6-l pa3 bg-blue blue">
  235. <div class="w-60-l">
  236. <p>Other interesting factoids that I could expand upon, you know, if only I had the <em>time</em>:</p>
  237. <ul>
  238. <li><a href="https://www.timeanddate.com/date/february-30.html">February 30 happened at least twice</a> in history.</li>
  239. <li><a href="https://www.reddit.com/r/askscience/comments/6c3t0s/if_each_day_is_only_23h56m4s_over_the_course_of_4/">An Earth “day” is different</a> from the time that it takes for the Earth to rotate on its axis once. This is because the Earth is <em>also</em> rotating around the sun at the same time, so that measurement is actually something like 361° of rotation instead of the normal 360°.</li>
  240. <li>You ever forget if “12am” means noon or midnight? I always felt stupid having to think about this every time, but I feel less bad after reading this <a href="https://ell.stackexchange.com/a/152729">excellent Stack Exchange answer</a> that details the entire history of this. My favorite part: the United States government decreed that “12am” meant “noon”… up until 2008, when the United States Government Printing Office reversed their position and swapped to using “12pm” as “noon”.</li>
  241. </ul>
  242. <p>Time is hard, and you’re not the only one screwing all this stuff up.</p>
  243. </div>
  244. </div>
  245. <div class="video">
  246. <video class="z-1" src="/video/utc-three.mp4" poster="/images/talks/utc/poster-three.jpg" width="100%" preload="" autoplay="" loop="" muted="" playsinline=""></video>
  247. <div class="absolute top-0 white z-2 w-50 mt2 ml5 o-80">
  248. <h1 class="lh-solid flex items-center">
  249. <div class="bg-green black dib tracked-tight avenir" style="padding: 0 2vw; margin-top: -10vw; font-size: 6vw">Code</div>
  250. <div class="dib white" style="font-size: 30vw">&amp;</div>
  251. <div class="bg-green white i dib tracked-tight avenir" style="padding: 0 2vw; margin-top: 10vw; font-size: 6vw">Time</div>
  252. </h1>
  253. </div>
  254. </div>
  255. <div class="pa6-l pa3 bg-green green">
  256. <div class="flex-l items-start">
  257. <div class="w-60-l">
  258. <p>While I was initially building this talk, I found myself listening to the words of my absolute favorite modern-day philosopher: Nas.</p>
  259. <blockquote>
  260. <p>You got CD-ROM, everythang operates by computers</p>
  261. <p>Then what happens when circuit breaks?</p>
  262. <p>Y2K’s the big scare</p>
  263. <p>Scientists say we ain’t prepared</p>
  264. <div class="mt4 tr i fw5">- Nas, "New World", 1999</div>
  265. </blockquote>
  266. <p>I’m not really sure what to take from all this, other than if Nas is really concerned about computer science and how it relates to time, then dammit, we should be concerned, too.</p>
  267. </div>
  268. <div class="w-40-l ml4-l">
  269. <img src="/images/talks/utc/nas.png" class="shadow-0" alt="Nasty Nas" />
  270. </div>
  271. </div>
  272. </div>
  273. <div class="pa6-l pa3 pt3-l bg-green green">
  274. <div class="w-60-l">
  275. <h2 id="storing-time">Storing Time</h2>
  276. <p>The very first thing you need to start worrying about when you build smart, time-aware software is how you store time. For many, databases will be the tool they’ll reach for. And there’s a lot of things to consider when it comes to <em>how</em> you store that data in a database.</p>
  277. <p>Step one: <strong>use UTC</strong>. Okay I’m not going to suddenly say all this advice we’ve been giving for years and years is wrong. UTC is a fine standard to base all your times off of. So use it. Don’t do something silly and <a href="https://twitter.com/awscloud/status/997174917908004864?lang=en">change your servers’ timezones from UTC</a>.</p>
  278. <p>Now, I’ve been burying the lede here for quite some time. It’s worthwhile to talk quickly about UTC, and why it’s a good default when we tell developers “Just use UTC”.</p>
  279. <p>UTC, of course, stands for:</p>
  280. <div class="courier">
  281. <blockquote>
  282. <p> <strong>U</strong>niversal<br />
  283. Coordina<strong>T</strong>ed…?<br />
  284. <del> <strong>C</strong> </del> um… lemme figure this out…
  285. <b>T</b>ime?<br /></p>
  286. </blockquote>
  287. </div>
  288. <p>Time standards bodies got us making scratch pads like some Zodiac Killer letter. Didn’t even know Ted Cruz cared about timezone issues.</p>
  289. <p>But yeah, this <code class="highlighter-rouge">UTC</code> initialism doesn’t make any sense. Let’s dig into this a little more.</p>
  290. <p>So you’ve got a bunch of scientist types around 1960 who are like, hey, time is all screwy we should totes make a standard. And some of them spoke English, and some of them spoke French, which, of course, is the cause of so much conflict over so many generations. (In hindsight, maybe we should have split all those troublemakers up from the start.)</p>
  291. <p>The English-speaking folk were like yo, this definitely sounds like <strong>Coordinated Universal Time</strong>, boom, ship it. And the French speakers were like yeah that makes total sense! <strong>Temps Universel Coordonné</strong> DOES work out well in our language, too, ship it! Then they both looked up and realized cool, they’ve created both <strong>CUT</strong> and <strong>TUC</strong> for acronyms. Shit.</p>
  292. <p>When your standard — that is expressly meant to <em>standardize</em> time — doesn’t even standardize on a standard <em>acronym</em>, well, damn, that probably doesn’t bode well for your standard.</p>
  293. <p>Or, actually, now that I think about it, this might be the most perfect metaphor about time itself ever created. Maybe we should give them some credit for that. Time never makes sense.</p>
  294. <p>Anyway, the compromise that arose was that if everyone is special, <em>no one is special</em>, so they created an entirely new set of letters that has no direct relation to any real words for the compromise: <strong>UTC</strong>.</p>
  295. <p>Whew.</p>
  296. <p>So. We use UTC because it has an <em>offset</em> of 00:00: in other words, it has no timezone offset. Other timezones are offset from <em>UTC</em>, not the other way around.</p>
  297. <p>It’s important to note that UTC is <em>not</em> GMT. GMT is Greenwich Mean Time, which historically was the center of time in the world. They both have an offset of 00:00. But you shouldn’t use GMT on your server, for example, because UTC is a <em>standard</em>, but GMT is a <em>timezone</em>. People actually live in locations whose time is GMT; UTC isn’t directly used by people (unless they’re really weird).</p>
  298. </div>
  299. <div class="flex-l items-start">
  300. <div class="w-60-l">
  301. <p>This may sound like such a small difference of wankery, but the more relevant part is that <em>some</em> users of GMT observe Daylight Saving Time (but not all). UTC has no concept of Daylight Saving Time at all. So if you base everything in GMT, well, who knowssss what will happen.</p>
  302. </div>
  303. <div class="w-40-l mt4 ml4-l bg-dark-green f6 pa3 br1 lh-copy flex">
  304. <div class="flex-column">
  305. <i class="fal mr3 fa-2x">lightbulb</i>
  306. </div>
  307. <div class="flex-column">
  308. <span class="fw5">Quick side note</span>: it's Daylight <em>Saving</em> Time, not Daylight <em>Savings</em> Time. You don't want to sound like a total tool in front of all six of us who care about this stuff.
  309. </div>
  310. </div>
  311. </div>
  312. <div class="w-60-l">
  313. <p>One question you might want to ask right from the start is: <strong>do you really <em>need</em> to store time?</strong></p>
  314. <p>As programmers, we’re kind of inherently built to want the ABSOLUTE BEST HIGHEST FIDELITY FORMATS OF ALL TIME. Like dammit, I <em>need</em> the timestamp down to the micromillinanosecond for every cheeseburger that gets added to my bespoke <em>Watch-The-BK-Throne</em> app. If I do not have this exact knowledge to the millisecond of when I consumed this BBQ Bacon WHOPPER® Sandwich From Burger King® I may die.</p>
  315. <p>But we sometimes don’t need all this data, and that’s cool, so be sure to ask yourself if you really need this data, or you just want this data. The rule of the game for programming with time is that you should opt to go as simple as possible as soon as possible. A good example of this are birthdays. Birthdays are kind of like floating events; it doesn’t really matter where you are on the planet; if the numerical day matches up with what’s on your driver’s license we’re set. Storing these things as a timestamp column instead of just a date column in your database can end up complicating your code down the line.</p>
  316. <h3 id="properly-storing-timezone-aware-times">Properly storing timezone-aware times</h3>
  317. <p>On the other hand, you may actually want to track time. In those cases, there’s a few ways of doing this, particularly if you know that fidelity of hour or minute is going to be important for your use case.</p>
  318. <p>Say you have an <code class="highlighter-rouge">events</code> table in your database, and you toss in a column to keep track of when the event starts:</p>
  319. <table class="bg-white mv4 center w-75 ">
  320. <thead>
  321. <th>Name</th>
  322. <th>Type</th>
  323. </thead>
  324. <tr class="striped--near-white">
  325. <td class="pa2">starts_at</td>
  326. <td class="pa2">timestamp</td>
  327. </tr>
  328. </table>
  329. <p>This is neat and obvious, since you want to store a time as a timestamp in whatever database you’re using. But if it’s important that you don’t end up being an hour off when something actually happened, you’d need to store the originating timezone as well:</p>
  330. <table class="bg-white mv4 center w-75 ">
  331. <thead>
  332. <th>Name</th>
  333. <th>Type</th>
  334. </thead>
  335. <tr class="striped--near-white">
  336. <td class="pa2">starts_at</td>
  337. <td class="pa2">timestamp</td>
  338. </tr>
  339. <tr class="striped--near-white">
  340. <td class="pa2">starts_at_tz</td>
  341. <td class="pa2">string</td>
  342. </tr>
  343. </table>
  344. <p>By adding the offset as a string in your database, you gain some additional powers. For one, it gives you a closer idea of when <em>specifically</em> the event happened.</p>
  345. </div>
  346. <div class="flex-l items-start">
  347. <div class="w-60-l">
  348. <p>One way to do this is to treat this column as an integer; say, store <code class="highlighter-rouge">-240</code> in a row to represent a shift of 4 hours (4*60 minutes). That’s cool, and it does get you closer, but again, we’re talking about a use case where it actually does matter to be as accurate as possible (and being off an hour might lead to nonsensical data). Just having a numerical offset doesn’t give you fidelity of location. Was it during Daylight Saving Time? What about comparing that to today’s time; do we account for DST or not? Also, do we need to account for changes in timezones that might have happened since that point in time?</p>
  349. <p>Instead of a numeric offset, use a string. Specifically, use the <a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">full qualified name</a> in the Olson database, so something like <code class="highlighter-rouge">Australia/Adelaide</code> or <code class="highlighter-rouge">America/Los_Angeles</code>. These are standardized descriptors of the timezones used in the world, and you can use these in pretty much every programming language ever used in the last few decades.</p>
  350. <p>Again, all of this probably isn’t relevant for <em>every</em> app — who cares if someone’s browsing the article <em>Brad Pitt’s Beautifully Coiffed Hair: Friend or Foe to the Proletariat?</em> and my six comments are <em>technically</em> listed as an hour earlier than they actually were. Regardless of timing, my comments were perfectly relevant and explored the issue perfectly. But for some apps it might make sense to get this detailed, particularly if you’re comparing a lot of times to each other (like, say, a calendar).</p>
  351. </div>
  352. <div class="w-40-l mt4 ml4-l bg-dark-green f6 pa3 br1 lh-copy flex-ns">
  353. <div class="flex-column">
  354. <i class="fal mr3 fa-2x">lightbulb</i>
  355. </div>
  356. <div class="flex-column">
  357. The historical side of this stuff gets kinda cool, too. One of my favorite examples is in <a href="https://tools.ietf.org/html/rfc3339#page-9">RFC 3339</a>:
  358. <div class="mv4 f7 bl b--white bw2 pl3">
  359. <b>1937-01-01T12:00:27.87+00:20</b><br /><br />
  360. This represents the same instant of time as noon, January 1, 1937,
  361. Netherlands time. Standard time in the Netherlands was exactly 19
  362. minutes and 32.13 seconds ahead of UTC by law from 1909-05-01 through
  363. 1937-06-30. This time zone cannot be represented exactly using the
  364. HH:MM format, and this timestamp uses the closest representable UTC
  365. offset.
  366. </div>
  367. So if you really get down into the rabbit hole and find yourself needing historically-accurate times across decades, you might need to backtrack over multiple previous timezone changes in order to get to that point.
  368. Also if you find yourself at this critical juncture, you might want to just give up programming entirely, because that sounds horrible.
  369. </div>
  370. </div>
  371. </div>
  372. <div class="mt5 flex-l items-start">
  373. <div class="w-60-l">
  374. <h2 id="transiting-time">Transiting Time</h2>
  375. <p>Aight, cool, you’re storing your times correctly; now we can take a look at how we transit those times to our clients.</p>
  376. <p>Number one rule: <strong>stay consistent</strong>.</p>
  377. <p>The number one way to address that number one rule: <a href="https://en.wikipedia.org/wiki/ISO_8601">ISO 8601</a>.</p>
  378. <p>ISO 8601 is one of my favorite standards and/or RFC out there. And yes, you <em>should</em> definitely have a favorite. (My all-time fave is <a href="https://tools.ietf.org/html/rfc2606">RFC 2606</a>, thanks for asking! I’m in awe of that absolute unit. Where would we be without that banger? We’d be in complete fucking chaos, that’s where.)</p>
  379. <p>ISO 8601 was a standard that came out in 1988, so it’s probably older than all you lot who are reading this, now get off my damn Friendster lawn. It was re-upped in 2004, 2014, and is anticipating a new draft by the end of this year. It basically defines THE way of writing a timestamp.</p>
  380. <p>Here: I’ll even be nice and show you an example:</p>
  381. <div class="ml4 f4 fw5">
  382. <script type="text/javascript">
  383. document.write(new Date().toISOString())
  384. </script>
  385. </div>
  386. <p>In JavaScript land, this is simple: it just uses the <code class="highlighter-rouge">toISOString()</code> function:</p>
  387. <div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">toISOString</span><span class="p">()</span>
  388. </code></pre></div> </div>
  389. <p>The astute among you might see a few reasons right away why this is such a dope format:</p>
  390. <ul>
  391. <li><strong>Easy sorting</strong>: It arranges all components from large to small, so pretty much any novice in a programming language could easily sort a list of timestamps from latest to oldest.</li>
  392. <li><strong>Timezone information</strong>: At the far end it includes the offset: <code class="highlighter-rouge">-08:00</code>, for example (well, not in this above example specifically, since in JavaScript you’d also need to parse this out manually with <code class="highlighter-rouge">getTimezoneOffset()</code>). This isn’t as high-fidelity as when we were talking earlier about storing the qualified string version of a timezone, but it does give us information we wouldn’t have otherwise. You don’t get this if you pass around <a href="https://en.wikipedia.org/wiki/Unix_time">UNIX epoch time</a>, for example.</li>
  393. <li><strong>No locale problems</strong>: You don’t have problems with Month/Day/Year formats getting confused with Day/Month/Year formatted dates. More on this in a few.</li>
  394. </ul>
  395. <p>So yeah, use ISO 8601 over the wire. It’s the most popular way of tackling a shared standard for time, so don’t be the jerk who does it in some fancypants custom manner.</p>
  396. <h3 id="rfc-3339">RFC 3339</h3>
  397. <p>Wanted to mention <a href="https://tools.ietf.org/html/rfc3339">RFC 3339</a> briefly as well, since sometimes you’ll see its mean mug pop up in APIs and other spots from time to time.</p>
  398. <p>RFC 3339 came out in 2002. This is a simplification, but it’s kind of a subset of ISO 8601. It requires timestamps — ISO 8601 allows you to omit them and just use it for a date — and in general it’s slightly more strict. It lets you get away with less.</p>
  399. <p>Effectively they’re sort of interchangeable. Most people and API platforms just say they comply with ISO 8601, so that’s probably going to be fine for you, too.</p>
  400. </div>
  401. <div class="w-40-l mt4 ml4-l f6 pa3 br1 lh-copy flex">
  402. <a href="https://xkcd.com/1179/" class="no-slide"><img alt="xkcd on ISO 8601" title="ISO 8601 was published on 06/05/88 and most recently amended on 12/01/04.
  403. See, that's the actual xkcd alt text for this; you didn't think I'd manually add it in this embed, did you. Well you're in luck: I did. Just for you, the xkcd obsessive. &lt;3" src="https://imgs.xkcd.com/comics/iso_8601.png" /></a>
  404. </div>
  405. </div>
  406. <div class="mt5 w-60-l">
  407. <h2 id="displaying-time">Displaying Time</h2>
  408. <blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">British press corp is locked outside the White House because our birthdates were submitted in UK format and secret service don&#39;t get it. 🇬🇧</p>&mdash; Jim Waterson (@jimwaterson) <a href="https://twitter.com/jimwaterson/status/825017459530936320?ref_src=twsrc%5Etfw">January 27, 2017</a></blockquote>
  409. <script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
  410. <p>You’ve got some time, you’ve sent it to the client or to the user… now you have to display it, with hopefully minimal amount of confusion with the United States Secret Service.</p>
  411. <p>I don’t know if you’ve noticed this yet, but Americans aren’t perfect. We use this fucked up date format, MM/DD/YYYY. Like under no circumstances does this make any sense. But if you switch that around and try to show someone from the US a date like 24/6/18… well that’s just going to be weird. People like their locale-based date formatting, and you should try to respect that as much as you can.</p>
  412. <p>One of the ways you can do this on the web is using the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl"><code class="highlighter-rouge">Intl</code> API</a>. <code class="highlighter-rouge">Intl</code> supports a number of different hooks and abilities to handle locale- and language-based changes for numbers, plurals, and dates and times.</p>
  413. <p>Beyond that, if you’re going to be doing anything fancier with dates and times beyond, say, just printing something to the page, you should really start using a proper time library. Things like adding two dates together while still tracking DST and a multitude of other time rules… well, it’s all really difficult to do yourself. Stand on the shoulders of giants, and steal from someone else. Just how Open Source was intended.</p>
  414. <p>Some solid libraries to take a gander at:</p>
  415. <ul>
  416. <li><a href="https://momentjs.com">moment.js</a> The classic time library in JavaScript. Date manipulation, formatting, pretty much everything you’d need.</li>
  417. <li><a href="https://date-fns.org">date-fns</a> More modern approach to a moment.js-like experience for handling dates on the web.</li>
  418. <li><a href="https://github.com/github/time-elements">github/time-elements</a> Web component extension to the <code class="highlighter-rouge">&lt;time&gt;</code> element. Also includes auto-updating timestamps, as well as some locale help.</li>
  419. </ul>
  420. </div>
  421. <div class="w-60-l mt5">
  422. <h2 id="accessibility">Accessibility</h2>
  423. <p>There’s something that tends to be left out of discussions about time (or discussions about any technology, really): accessibility. There’s a few things here that you can do for your human users and computer users that’ll help everyone out.</p>
  424. <p>In a lot of hip social apps, you’ll have something like this:</p>
  425. <p><img src="/images/talks/utc/social-mockup.png" alt="Mockup of social app" /></p>
  426. <p>And on the bottom footer of that component you’ll frequently see a relative datestamp:</p>
  427. <p><img src="/images/talks/utc/relative-datestamp.png" alt="Relative datestamp" /></p>
  428. <p>That’s all well and good, but there’s a few problems with this. For one, this doesn’t automatically update on-page, so if you open the page in a tab an hour ago, it’ll still show something as happening a couple minutes ago. Step one might be to have a lightweight timer on your page that auto-updates all relative date/times and updates them every minute. Keeps everything fresh.</p>
  429. <p>Secondly, as time moves on you’ll start seeing a lot of stuff like this:</p>
  430. <p><img src="/images/talks/utc/relative-year.png" alt="Relative year" /></p>
  431. <p>I always hate stuff like this, because I’m always like, well, when the fuck did this actually happen? Like does this mean five months ago and they’re rounding up to a year? Or does it mean 23 months ago, which is wayyyy different from five months ago? WHAT DOES “ABOUT” MEANNNNN?</p>
  432. <p>A few things you can use here. One of the things I always liked about GitHub is that they’ve always shown a full timestamp in the <code class="highlighter-rouge">title</code> of any relative time on-page. I think we started adding that way back in 2010 or so, something like that. Always made it really easy to find out when specifically some event happened: you just mouseover the element.</p>
  433. </div>
  434. <div class="w-80-l mv4">
  435. <video class="shadow-2" src="/video/utc-github-relative-titles.mp4" poster="/images/talks/utc/poster-github-relative.jpg" width="100%" preload="" autoplay="" loop="" muted="" playsinline=""></video>
  436. </div>
  437. <div class="w-60-l">
  438. <p>You can achieve this by just dropping this data into a <code class="highlighter-rouge">&lt;span&gt;</code>, but the best practice nowadays is to use the <code class="highlighter-rouge">&lt;time&gt;</code> element. So you print things relatively like usual:</p>
  439. <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;time&gt;</span>six minutes ago<span class="nt">&lt;/time&gt;</span>
  440. </code></pre></div> </div>
  441. <p>Then you add a human-friendly string to the <code class="highlighter-rouge">title</code> attribute:</p>
  442. <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;time</span> <span class="na">title=</span><span class="s">"May 28, 2018, 3:47 PM PST"</span><span class="nt">&gt;</span>six minutes ago<span class="nt">&lt;/time&gt;</span>
  443. </code></pre></div> </div>
  444. <p>The last bit is that the <code class="highlighter-rouge">&lt;time&gt;</code> element also allows for a <code class="highlighter-rouge">datetime</code> attribute. This is a way to get past all your fancy relative formatting, or human formatting, and let clients parse out the <em>actual</em> timestamp correctly. If you’re wondering how you format this particular string, you haven’t been reading at all (and you’re going to miss all my good time puns, you heartless fiend, so go read it a <em>second</em> time).</p>
  445. <p>But yes: it’s our pal the friendly ISO 8601-formatted string. It’s everywhere!</p>
  446. <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;time</span> <span class="na">title=</span><span class="s">"May 28, 2018, 3:47 PM PST"</span> <span class="na">datetime=</span><span class="s">"2018-05-28T15:47:57-08:00"</span><span class="nt">&gt;</span>six minutes ago<span class="nt">&lt;/time&gt;</span>
  447. </code></pre></div> </div>
  448. <p>If you ever print out a relative date or time to a page, you should follow this format everywhere. Extract it into a component or utility function or however it is your weirdo team does it, and you’ll make the most amount of people happy.</p>
  449. </div>
  450. <div class="w-60-l mt5">
  451. <h2 id="inputting-time">Inputting time</h2>
  452. <p>I don’t know if you’ve tried date pickers and time pickers over the years, but they’re awful.</p>
  453. <p><img src="/images/talks/utc/pickers.png" alt="Date pickers" /></p>
  454. <p>Maybe it’s just me, but I still haven’t found the perfect time and date picker yet. Either there’s accessibility problems, or design problems, or dependency and size problems, or something else entirely. This probably why there are so many of them: everyone says the same thing and tries to reinvent the wheel, thus perpetuating the cycle. I’m sure During will feel the need to create and open source our own at some point, too.</p>
  455. <p>Part of this stems from there not being a real, viable browser option. At a certain point browser makers realized this was a problem and got to work on adding <code class="highlighter-rouge">type=date</code> and <code class="highlighter-rouge">type=time</code> to the verable <code class="highlighter-rouge">&lt;input&gt;</code> element. And that sort of worked.</p>
  456. <p>Here’s <code class="highlighter-rouge">&lt;input type="date" /&gt;</code> in Chrome:</p>
  457. <video class="shadow-2 mv3" src="/video/utc-type=date.mp4" poster="/images/talks/utc/poster-type=date.jpg" width="100%" preload="" autoplay="" loop="" muted="" playsinline=""></video>
  458. <p>It… you know, works. Ugly as sin, though, and that’s the first problem: there aren’t enough hooks into the element to comprehensively style it as you’d like.</p>
  459. <p>Here’s <code class="highlighter-rouge">&lt;input type="time" /&gt;</code> in Chrome:</p>
  460. <video class="shadow-2 mv3" src="/video/utc-type=time.mp4" poster="/images/talks/utc/poster-type=time.jpg" width="100%" preload="" autoplay="" loop="" muted="" playsinline=""></video>
  461. <p>Also, here’s <code class="highlighter-rouge">&lt;input type="date" /&gt;</code> in Safari:</p>
  462. <video class="shadow-2 mv3" src="/video/utc-type=safari.mp4" poster="/images/talks/utc/poster-type=safari.jpg" width="100%" preload="" autoplay="" loop="" muted="" playsinline=""></video>
  463. <p>Safari, continuously behind on virtually every interesting standard on the planet these days, doesn’t support it at all. So yeah, everything is terrible.</p>
  464. <p>I asked someone far more knowledgeable than me on <code class="highlighter-rouge">&lt;input&gt;</code> about when we can finally start using a cross-platform, extensible, great option for date pickers. Her answer was an immediate <strong><em>oh god probably never</em></strong>. Neat! The web is great!</p>
  465. <p>So yeah, at the end of the day I’ve taken peace with trying to find the best crappy option, restyling it so it doesn’t look terrible, and then ignoring it and throwing my laptop into a lava flow. Just make peace with it.</p>
  466. </div>
  467. <div class="mt5 w-60-l">
  468. <h2 id="recurring-events">Recurring events</h2>
  469. <p>If someone held a gun to your head and demanded in the next week you either 1) programmed a comprehensive system that included full support for recurring events, or 2) invent full-scale ready-to-go-to-market cold fusion, then you should abolutely start brushing up on atomic physics. Recurring events is a true shit show.</p>
  470. <p>It starts normally enough, of course. You have an innocent phrase that you want to apply to your system, like:</p>
  471. <div class="ml5 fw5 f4">"Every Tuesday at 2pm"</div>
  472. <p>Awesome. So you start modeling it in your database. You say, hey, I’ll just create an event with a <code class="highlighter-rouge">starts_at</code> value of next Tuesday. And then you save another row for the Tuesday after that. And then another row for the Tuesday after that. And after that. And after that. You do this for 70 occurrences before you start realizing, hey, I think this goes to infinity. (Don’t ask me why it took you that long to figure this out; you’re the one who’s a little slow on the update. I figured it out by the 52nd occurrence.)</p>
  473. <p>Being that even AWS doesn’t have a hard drive with literal infinite space (yet), you realize you need to figure out another way to deal with this. Maybe you can just create a shorthand of rules that defines when things happen.</p>
  474. <p>Martin Fowler has a <a href="https://martinfowler.com/apsupp/recurring.pdf">really great whitepaper</a> on recurring events. It’s short, and walks you through figuring all this out in code-agnostic, plain English. (Definitely check it out if you get really excited about reading whitepapers. Also get yourself checked out if that’s actually the case.)</p>
  475. <p>Fowler called these shorthands <em>temporal expressions</em>. It’s a way of defining the problem space so your system can do something with it. And luckily, we have a standardized way of thinking about this, too, in <a href="https://tools.ietf.org/html/rfc5545">RFC 5545</a>. These are called <code class="highlighter-rouge">RRULEs</code>, or <strong>recurrence rules</strong>. So “Every Tuesday” might look like this:</p>
  476. <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>FREQ=WEEKLY;BYDAY=TU;INTERVAL=1
  477. </code></pre></div> </div>
  478. <p>By using something like this, you basically can get away with pre-generating only <em>one</em> event/instance/recurrence, and then in your client, or in-memory, or through some other approach, you generate these occurrences on-demand as you go.</p>
  479. <p>This might seem simple enough. And for very simple cases, yeah, it might not be too bad. But it’s all just a race against <em>time</em>. Because:</p>
  480. <ul>
  481. <li>What about Daylight Saving Time? If this is a time accessed by multiple users, whose particular brand of DST wins out? What happens if you observe DST but I don’t?</li>
  482. <li>What about exceptions? Maybe one of the Tuesdays is a holiday, so you don’t want to have an occurrence on that day.</li>
  483. <li>What about exceptions that are subsequently moved? Say Tuesday is a holiday, so we move it to Wednesday. Oops, no now we’ve moved it to Thursday. How do we efficiently model all that without going nuts?</li>
  484. </ul>
  485. <p>The erm… rules… in <code class="highlighter-rouge">RRULE</code> all handle this. There are rules like <code class="highlighter-rouge">EXDATE</code>, <code class="highlighter-rouge">EXRULE</code>, <code class="highlighter-rouge">UNTIL</code>, <code class="highlighter-rouge">DTEND</code>, <code class="highlighter-rouge">COUNT</code>, and many more. It’s an attempt to help model all of these extra problems you might run into… but at the expense of really cluttering up your domain logic.</p>
  486. <p>My advice for all of this is to go as simple and as inefficient as you can, at least initially. I guess that’s the opposite of what our usual goals are in software, but I think it’s good advice for time code. The more complex your time logic is, the more it picks up steam, like a snowball rolling down a cliff. Every little bit adds up and compounds.</p>
  487. <p>So try going simple at first, if you can. Instead of modeling a <code class="highlighter-rouge">RRULE</code> for a weekly reoccurrence, maybe you can just pre-generate all of the events ahead of time, but just for a year. Then on January 1, regenerate a new set of events in your database. This makes it 1) easy to reason about, 2) easy to query (it’s just a normal SQL query), and 3) gives you the benefit of having real database records backing each of your events (once you generate “virtual” events through <code class="highlighter-rouge">RRULEs</code>, it makes things like associations that much harder, since you don’t have a database ID to associate with).</p>
  488. </div>
  489. </div>
  490. <section class="mt6">
  491. <div class="center lh-copy dark-blue f3 white w-60-l pa3">
  492. <p class="ma0 f2"><span class="pink">Programming time</span> is pretty weird.</p>
  493. <p class="mv5">It can sometimes make you feel week in the knees, and very days and confused about how it all fits together. But watch it: this is hour burden to bear, and we can't just let it past us over.</p>
  494. <p class="mv5">
  495. We've been working on building <a href="http://during.com">During</a> for awhile now, and most of the time I've been tryna keep my sanity, but every now and then I take a step back and say wait a minute, how does any of this work? How does society work? Do users actually need all-day, floating, recurring events with exceptions spread over multiple Daylight Saving Time boundaries? Or should I just go tell users to eat one and go live a simpler life in the woods?
  496. </p>
  497. <p class="mv5">Anyway, what I mean is that I've been in time-headspace for awhile now. Here's a few last thoughts:</p>
  498. <p class="mv5"><span class="pink">Keep everything simple</span> as much as possible. Even if it means being really inefficient, or redundant, or ugly. Everything adds up, and I think usually programmers overthink time. (Leave overthinking for the times where it's actually critical to overthink.)</p>
  499. <p class="mv5"><span class="pink">Handle more in the client.</span> This is a little bit of an odd piece of advice, but especially when you have a central service (GraphQL, REST API, some central interface, particularly when hooked up with a single page app, mobile clients, or other clients), I think it's more important to have as simple a central service as possible. This means it should basically only speak UTC, and might not even handle a lot of the more complicated logic around recurring events, timezones, and so on. It adds redundancy in your clients, but I think it makes it easier to understand overall.</p>
  500. <p class="mv5"><span class="pink">Leverage standards</span> and let others do the heavy lifting. Obviously that means using the <em>Brightest Point in Human History</em>, also known as ISO 8601, but it also means using premade time libraries, resources like the Olson database, and leveraging other people's existing work as much as possible. Let someone else figure out the really gnarly edge cases so you can work on your domain's edge cases.</p>
  501. <p>Anyway, our time is up. ⌚️👀</p>
  502. <h2 class="mt6 db">Additional reading</h2>
  503. <p class="mv5">And finally, now that I've suckered you into caring this much about time, you might want to keep on reading. Here's some interesting links if all this text wasn't enough for you:</p>
  504. <ul class="list ml0 pl0 f5 links-list lh-copy">
  505. <li><a href="http://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time">Falsehoods Programmers Believe About Time</a> and its sequel, <a href="http://infiniteundo.com/post/25509354022/more-falsehoods-programmers-believe-about-time">More Falsehoods Programmers Believe About Time</a>. These get into some really nitty-gritty on programming time edge cases and weird things to keep in mind as you go. Lovely stuff, and if you haven't read them yet (or even if you haven't read them recently), you should go and give 'em a read now.</li>
  506. <li>There's a ton of amazing things to learn on the Wikipedia page for <a href="https://en.wikipedia.org/wiki/Unix_time">Unix time</a>. I started including some of these things here and there, but really you should just go through the whole thing. There's a lot of talk about Unix and how they deal and think about time. Some nice little nuggets in there, like why Unix epoch came before the standardization of UTC, and why the epoch is not exactly the number of seconds since 1970 (see: leap seconds).</li>
  507. <li>I don't know what my favorite George Carlin bit of all time is (okay, I do: it's <a href="https://www.youtube.com/watch?v=MvgN5gCuLac"><em>Stuff</em></a>), but <a href="https://www.youtube.com/watch?v=zaR3sVpTB98">this bit on time</a> is pretty great too. He had a way with words.</li>
  508. <li>From Hodinkee: <a href="https://www.hodinkee.com/articles/why-clocks-run-clockwise">Why do clocks run clockwise?</a> — I love stuff like this.</li>
  509. <li><a href="https://nylas.com/blog/rrules/">The deceptively complex world of calendar events and RRULEs</a>. Great post on breaking down how to think about RRULEs from a calendaring and system perspective.</li>
  510. <li>Wikipedia's <a href="https://en.wikipedia.org/wiki/Time_formatting_and_storage_bugs">Time formatting and storage bugs</a> is worth a look just for the sheer number of upcoming time-related bugs we know are coming. Y2K was just the start.</li>
  511. <li>The <a href="https://en.wikipedia.org/wiki/Happy_Monday_System">Happy Monday System</a>, which honestly I just loved based on the name of it alone. Shows how Japan has moved their holidays schedules around just to make people happier with a longer weekend.</li>
  512. <li>Time smearing links <a href="https://developers.google.com/time/">from Google</a> and <a href="https://aws.amazon.com/blogs/aws/keeping-time-with-amazon-time-sync-service/">from Amazon</a>. I didn't even get to cover time smearing, leap seconds, leap years, and all of the little ways we correct how we measure time. Leap seconds are a pretty interesting subject, particularly since they're nonstandard: the need to add another leap second can depend on if a lot of seismic activity happened recently, for example.</li>
  513. <li>Another plug for reading <a href="https://tools.ietf.org/html/rfc3339">RFC 3339</a>. It's very clearly written, not too long, and has a lot of examples like the aforementioned 1937 Netherlands example, as well as how they suggest displaying a leap second in an RFC 3339-formatted string, and the possibility of only emitting UTC time from a server as a security precaution. ("Others might consider this to be loss of useful functionality at the hands of paranoia.")</li>
  514. </ul>
  515. </div>
  516. </section>
  517. <div class="mt6 ph3 f4 bg-pink pa4">
  518. <div class="mv5 flex w-60-l center">
  519. <div class="flex-column tc" style="min-width: 120px">
  520. <img src="/images/holman.jpg" alt="Holman's avatar" class="br-100 shadow-0 b--white ba bw3" width="100" height="100" />
  521. </div>
  522. <div class="flex-column ml4 lh-copy">
  523. <div class="f3"><a href="/about">Zach Holman</a></div>
  524. <div class="mv4">I cofounded <a href="http://during.com">During</a>, a neat new calendar for people who <em>live</em> in their calendar.</div>
  525. <div class="mv4">I swear we're going to ship it soon, too.</div>
  526. <div class="mv4"><a href="https://twitter.com/holman">Follow me on Twitter</a> and I promise I won't waste your... <em>time</em>.</div>
  527. <div class="mv4 f6">I also promise that was the last pun.</div>
  528. <div class="mv4 f6">...until next time!</div>
  529. </div>
  530. </div>
  531. </div>