Profile cover photo
Profile photo
Sam Neubardt
About
Sam's posts

Post has attachment

Post has attachment

Post has attachment
my new blog

Post has attachment
so good, smash patriarchy!

via +Samantha Lifson

Post has attachment

Post has attachment

perfect night for snow biking :D

Post has attachment
Spicy sweet potato fries! 
Photo

Spent a couple of hours tracking down a weird bug with dates in JS, so please allow me to decant some knowledge that resulted from this afternoon's toils.

Some Background
Entities in the application have a datetime field and are persisted in the GAE data store. The data store treats all dates/times as being in UTC (as it should, since timezones are part of the presentation layer). I'd already validated that the datetimes of entities in the data store were correctly stored as UTC.

A date is passed into the application's javascript when the containing page is rendered. It was passed as a date string, e.g. new Date("8/5/11 14:22")
A loop would increment the date by constructing a new date like this:
var nextDay = new Date(startDate.getTime() + 86400000);
Calling startDate.setDate(startDate.getDate() + 1) doesn't work because it won't increment through to the month or year (e.g. increment 12/31 won't result in 1/1). Adding to the unix time representation of the date will.

The Problem
The application is supposed to display dates as UTC but some were displaying as UTC + 5 (i'm in EST). The UTC time would be accessed through the getUTC* methods on a date object.

The Solution
There's a subtlety with the Date constructor (subtle as in i didn't realize it and didn't see it explicitly documented anywhere). Unix timestamps are in GMT and the Date constructor treats them as such. However, date string's without a timezone are treated as in the browser's timezone.

Some examples:
new Date("8/5/11 12:11").getHours() // => 12
new Date("8/5/11 12:11").getUTCHours() // => 17

// 1312586961 == Fri, 05 Aug 2011 23:29:21 GMT
new Date(1312586961000).getHours() // => 19
new Date(1312586961000).getUTCHours() // => 23

Setting a Date using a unix timestamp will always assume that the timestamp is in UTC. Setting a date using a datestring will assume it's in the user's local time zone if not otherwise specified.

The bug was caused by constructing a Date with a datestring that represented a time in UTC without a timezone in the string. The time was interpreted to be in EST (so getHours was in UTC and getUTCHours was in UTC + 5).

var today = new Date("8/5/11 12:11") // in UTC
var tomorrow = new Date(today.getTime() + 86400000)
Since it's expected that getTime will return a timestamp in UTC and that today was constructed with a local time it converts that UTC time to UTC again (shifting it forward 5 hours). So tomorrow is actually 1 day & 5 hours ahead.

Post has attachment
checkout my blog discussing the science of trucks & their (currently unknown) origins with plenty of juicy pics
Wait while more posts are being loaded