JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.48k stars 5.46k forks source link

Interface to Date/DateTime Internal Representation #10121

Open quinnj opened 9 years ago

quinnj commented 9 years ago

So this has come up a few times on the mailing list and I wanted to throw out a few ideas I had + get some feedback/other ideas.

The issue is that sometimes it's nice to be able to work with the integer representation of a Date/DateTime, perhaps for serializing or whatnot, and we currently don't provide a consistent interface.

Currently, you can do:

In  [20]: t = now()

Out [20]: 2015-02-07T22:02:02

In  [21]: int(t)

Out [21]: 63559029722000

In  [22]: Dates.value(t)

Out [22]: 63559029722000

In  [23]: t.instant.periods.value

Out [23]: 63559029722000

to get the integer representation of a DateTime, but the only way to turn that back into a DateTime is through:

In  [24]: DateTime(Dates.UTM(int(t)))

Out [24]: 2015-02-07T22:02:02

To make it more consistent, here are a few proposals:

I'm not quite sure what I prefer (which is why I opened this issue), so I'd appreciate any thoughts. If anything, I kind of lean towards option 1, which would at least be overall consistent, though perhaps a little verbose.

nalimilan commented 9 years ago

Not a complete proposal, but: I don't really like int() or date2value(), as they do not convey any meaning about what the value represents. To me UTM() and UTD() make more sense.

vtjnash commented 9 years ago

i wonder if it might make sense to only define conversion to/from integers as addition/subtraction operations on date intervals. i haven't really looked at what is already being done in this regard, however.

UnixEpoch + seconds(63559029722000)
seconds(now() - UnixEpoch)
StefanKarpinski commented 9 years ago

I'm pretty suspicious of any name that has to include a 2 or to in it since, like having underscores to separate words, that seems to me to be a sure sign that you could break things down into smaller, more atomic concepts. I would tend to prefer Dates.rata2datetime(x) and Dates.datetime2rata(y) as some kind of conversion – i.e. convert(Dates.Rata, x) and convert(Dates.DateTime, y). Also shorter in this case. So similarly, I'd prefer to not to introduce more 2 functions for this. Ideally, it would be great to figure out a way to express this functionality in a functional way. What I mean by that is to have people write it in a way that implies the computation and just make it convenient. One thing that comes to mind is that we already have trunc, round, ceil and floor methods that take a precision argument, and that's really very close to what this is doing, but of course with a division somewhere in there, so I'm not sure how to fit that in. What is the computation that's going on here, exactly?

aviks commented 9 years ago

I suppose the computation happening here is to display the internal storage of a Date object. The Date object itself being the representation of a point in time. And the reverse, create a Date object given its internal representation.

The best analogue is probably Float64. So a Float64 is is a representation of a point on the number line. But a Float64 object is stored as a 64 bit binary number. So a similar computation would be reinterpret(Uint64, Float64) which is quite hack-y. And the reverse being hex-literal floats. So while it is a conversion, its not the same sense as converting an Int to a Float.

quinnj commented 9 years ago

@aviks is right, we're not really converting here as much as returning the internal representation of the DateTime and Date types (which are stored as Int64s).

@StefanKarpinski, I think it would certainly be a good idea however to rework the conversion functions to be more inline with your comments above. The relevant code is pretty short and sweet and could use a better interface: https://github.com/JuliaLang/julia/blob/1d4e75283ebcec815ef79efd3fca25360648289c/base/dates/conversions.jl

StefanKarpinski commented 9 years ago

Is it really the internal representation that one wants? It seems to me that one wants a value that happens to also be the internal representation, but there's a semantic meaning to that value that is why one wants it. If you're going to hope to write generic code that doesn't care about internal representation, it's going to have to be independent of that, even if it's the same in the common case.

quinnj commented 9 years ago

I'm not sure; my intuition is that people actually want the internal representation because they're doing something that involves needing a lowest common denominator of types (i.e. int, double, etc.); this might be marshalling values between places or otherwise interacting with a binary storage of some kind. In that case, you'd want to store just the physical Int64 of the Date/DateTime with a note that to unmarshal, you'd call Date(Dates.UTD(x)) to get a Date back.

Maybe others can chime in with potential use cases and what they're really after here.

quinnj commented 9 years ago

And more to your point, @StefanKarpinski, we do already have the "internal representation" with semantic meaning in the UTInstant type. Maybe we just need to provide a Dates.instant(::Date) function to get that "machine representation of time" out to the user. But as I mentioned above, I think in the cases I've heard of so far, they actually need to boil it down to an Int64.

pao commented 9 years ago

rata2datetime

Perhaps this is out of turn as a native English speaker, but I do wonder how comprehensible the "2"->"to" pun is for non-native speakers? Should we consider avoiding that particular shorthand (in whatever context, not just this one)?