Skip to content
This repository has been archived by the owner on Sep 18, 2023. It is now read-only.

Implicit local timezone assumed in Epoch #26

Open
aviks opened this issue Jul 10, 2015 · 5 comments
Open

Implicit local timezone assumed in Epoch #26

aviks opened this issue Jul 10, 2015 · 5 comments

Comments

@aviks
Copy link

aviks commented Jul 10, 2015

So I am currently in British Summer Time, which is GMT-1 ie, one hour ahead of GMT. At the time I did this, the local time was 52 minutes past 4 in the afternoon.

It seems like the datetime2unix and unix2datetime functions in julia consider the epoch to be 1-1-1970 00:00:00 localtime while both OSX and Java consider the epoch to be 1-1-1970 00:00:00 GMT. This causes issues when converting between the two. What would you think is the best way of handling this?

I realise dates doesn't do full timezones at this time, I still think this assumption of local time in epoch is a bit suspect.

shell> date
Fri 10 Jul 2015 16:52:42 BST

julia> jd=(@jimport(java.util.Date)(())); jld=Dates.now(); t=int(time());

julia> jcall(jd, "toString",JString, ())
"Fri Jul 10 16:52:47 BST 2015"

julia> jld
2015-07-10T16:52:47

julia> div(jcall(jd, "getTime", jlong, ()), 1000)
1436543567

julia> int(Dates.datetime2unix(jld))
1436547167

julia> t
1436543567

julia> int(Dates.datetime2unix(jld)) - div(jcall(jd, "getTime", jlong, ()), 1000)
3600

julia> Dates.unix2datetime(jcall(jd, "getTime", jlong, ())/1000)
2015-07-10T15:52:47.17

julia> Dates.unix2datetime(t)
2015-07-10T15:52:47
@aviks
Copy link
Author

aviks commented Jul 10, 2015

cc: @quinnj @StefanKarpinski

@quinnj
Copy link
Owner

quinnj commented Jul 10, 2015

It's not the datetime2unix and unix2datetime functions, it's the use of Dates.now(). Dates.now() returns the local time as a DateTime type that inherently doesn't associate a timezone with it. When you call jcall(jd, "toString",JString,()), there's inherently a timezone tied to that Java date, so when you convert it to an integer, it's correctly shifting to GMT. We don't do that since there is no timezone inherently associated with our DateTime type. Hopefully that makes sense? You can call now(Dates.UTC) to get a DateTime according to GMT instead of local time which will correspond to your java dates and time().

@aviks
Copy link
Author

aviks commented Jul 11, 2015

This may be a matter of perspective, but I'm not particularly convinced yet.

I think it comes down to the definition of that 10 digit number. In both Java and Unix, it is defined as number of seconds since 1-1-1970 00:00:00 GMT. Not that the epoch is defined as GMT, not local time. Defining the epoch at GMT ensures that each instance in time, at any place on earth, can be described by the same number (modulo relativistic effects, or leap seconds). If you define epoch based on local time, then that number does not define an instance in time, you need a number and a location.

Hence I think Dates.datetime2unix(dt) should return a number based on this definition above. Which means that there is an implicit assumption about the timezone of dt in the datetime2unix call. And currently the assumption is that dt is in GMT, which is different from the assumption in now()

I think the inconsistency is best illustrated by the following invocation. I would expect that Dates.now() and unix's now converted via unix2datetime should return the same result. no?

julia> Dates.now()
2015-07-11T00:25:26

julia> Dates.unix2datetime(time())
2015-07-10T23:25:27.583

Having written all that however, I am not sure if full consistency is possible without the full TZ db.

PS: FWIW, the java Date type does not store any TZ information. Similar to julia the now() equivalent, which is the default constructor of that type, returns the current local time.

@StefanKarpinski
Copy link

StefanKarpinski commented Jul 11, 2015 via email

@quinnj
Copy link
Owner

quinnj commented Jul 11, 2015

@aviks, let me stress again, the confusion/problem is not in datetime2unix/unix2datetime, which are very straightforward methods. Let's breakdown what everything is doing here:

  • unix2datetime takes the # of seconds since 1970-01-01T00:00:00 GMT and converts to a DateTime
  • datetime2unix takes a Julia DateTime and converts it to the # of seconds since 1970-01-01T00:00:00 GMT, with an implicit assumption that the DateTime instance is GMT
  • now(Dates.UTC) returns the current wall-time as a DateTime in GMT
  • now() returns the current wall-time as a DateTime adjusted according to the local system locale

I think your confusion comes from the fact that now() is returning a DateTime that will show exactly what I see in the corner screen of my system, yet that DateTime type is inherently non-timezone aware, so passing that value to datetime2unix falls prey to the "implicit assumption that the DateTime is GMT".

We really can't do any better with the current, minimal Base implementation. We could change now() to return the current wall-time in GMT and have a separate now(Dates.LOCAL) option for current wall-time according to system time, but that's 6s to me vs. the current setup.

My point about Java being timezone aware is the fact that when you ask for the current date, they're implicitly doing now(Dates.UTC) to get the # of unix seconds, but when you call toString, it's automatically grabbing whatever TimeZone.getDefault() is set to (local system settings) and displaying that GMT unix seconds to you in a nice, pretty string adjusted according to your local system's offset from GMT. It's actually storing GMT.

I guess that's another possible approach that may be less subtle for users. now() always returns GMT, and we add the ability in Dates.format(dt, formatstring; local=true), so that it's explicit you want to adjust the output string to show what your current system is showing in the corner of your screen. I'd be ok with that.

Really though, I should just finish up TimeZones.jl and if a user is ever wading into territory of needing to deal with timezones, they should automatically hook into that.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants