spencermountain / spacetime

A lightweight javascript timezone library
http://spacetime.how/
Other
3.99k stars 184 forks source link

support `Date.toString()` format #148

Open corysimmons opened 5 years ago

corysimmons commented 5 years ago
t = spacetime('Mon Jun 17 2019 11:00:00 GMT-0700 (Los Angeles Daylight Time)')
console.log(t.tz) // america/los_angeles
console.log(t.time()) // 4:00pm

t = t.goto('America/New_York')
console.log(t.tz) // america/new_york
console.log(t.time()) // 5:37am <-- I would've expected 7:00pm

It seems goto just changes the location of the timezone but doesn't keep the moment. It just returns the current time in that timezone...?

spencermountain commented 5 years ago

hi cory, whoa, this looks like a bug. i think it has something to do with the input date formatGMT-0700, is this some date standard from somewhere? I'm happy to support it.

you're right though. I think the 5:37am is crazy. Will check it out today or tomorrow.

spencermountain commented 5 years ago

fwiw, this date format seems to be supported, if it helps: Mon Jun 17 2019 11:00:00 -0700

corysimmons commented 5 years ago

It's the JS string output of a Date object. I don't think it's a standard, but it was cool that your lib read it. To demonstrate, it technically can be used like so:

new Date(
  String(
    new Date(2020, 1, 1)
  )
)

(if anyone is reading this and shaking your head at trying to use a JS date string like this then please correct me)


I'm somewhat new to JS dates and have been throwing everything at libs. I just recently found out UTC Everything!!! is a thing.

Just thought this was weird behavior... I reckon you use new Date() behind the scenes?

spencermountain commented 5 years ago

hahaha i appreciate that, thank you.

spencermountain commented 5 years ago

just reading about this, it seems Date.toString() returns a made-up javascript date format.

it's well-documented here, for future-me.

not sure how this should relate to the informal-timezone parsing stuff. I think we could get-away with ignoring the los angeles stuff, and just setting it to UTC-7, at first.

spencermountain commented 5 years ago

another note to myself:

d.toDateString()
"Fri Jun 28 2019"

d.toGMTString()
"Fri, 28 Jun 2019 16:26:14 GMT"

d.toISOString()
"2019-06-28T16:26:14.797Z"

d.toJSON()
"2019-06-28T16:26:14.797Z"

d.toLocaleString()
"6/28/2019, 12:26:14 PM"

d.toLocaleTimeString()
"12:26:14 PM"

d.toSource()
"(new Date(1561739174797))"

d.toString()
"Fri Jun 28 2019 12:26:14 GMT-0400 (Eastern Daylight Time)"

d.toTimeString()
"12:26:14 GMT-0400 (Eastern Daylight Time)"

d.toUTCString()
"Fri, 28 Jun 2019 16:26:14 GMT"

we should just loop around a ton of dates, and input->output, and make sure the Date objects are the same. There's bound to be a bunch of gotchas.

corysimmons commented 5 years ago

I'd definitely use IANA timezone names instead of +/- hour offsets. There is a ton of data associated with these that shouldn't be ignored.

https://medium.com/@toastui/handling-time-zone-in-javascript-547e67aa842d grep IANA

corysimmons commented 5 years ago

I suspect 99.999% of datetime use cases should be:

  1. Generate date using JS date. Convert to UTC+0.
  2. Grab the client's IANA timezone with jstz.
  3. Stash both of those in a db on the server.
  4. All servers you work with should be config'd to be UTC+0. (most are by default)
  5. When a client goes to consume a date from the server, fetch the UTC and IANA. Do all operations on that UTC+0.
  6. If you ever need to display a date to the client, return a fresh (immutable) string that has been formatted with a relevant IANA.

Every single other pattern seems to touch new Date which infests the timestamp with confusing offset data.

I hate datetimes. :( Curious what your thoughts are on that pattern ^

spencermountain commented 5 years ago

yep, I think you're right.

it took me a long time to come to your conclusion, about how new Date has the sneaky offset thing. I'm surprised it hasn't been discussed further.

yeah, because the calendar changes on a political basis, a time string means whenever that time will be.... So, like you said, you need UTC calendar info, and a iana zone. Unfortunately iso dates don't usually have a IANA zone. I think most solutions involve setting a iana in a user table and making some (usually correct) assumptions.

also, IMO it doesn't matter the details about when/where the date was made, and what the offsets looked like at that time. If i say 'lets meet a year from now' and the politicians change the dst around, we're gonna meet 'less than a year from now', or whatever. That's just my opinion though.

hope that helps.

spencermountain commented 5 years ago

there's plenty of cranky blog posts out there, without real advice, but I'd say most people end up storing an ISO string, then write edge-cases for any weird 11:59 dates, if they care.

if users travel to another timezone, they expect confusion. It's really a UX issue, more than an engineering one.

when engineers are launching missles or something, they do a organization-level ad-hoc management solution. There's not a real standard. /twocents!

corysimmons commented 5 years ago

I had to start getting the client's IANA with https://www.npmjs.com/package/jstz :D

But yeah I 100% agree with your rant (and all the blog post rants) on how bad time stuff is.