#2267 DateTime.fromJava() returns null?

SlimerDude Sat 19 Apr 2014

DateTime has a handy fromJava() method which:

Create date for Java milliseconds since the epoch of 1 Jan 1970 using the specified
timezone (defaults to current). If millis are less than or equal to zero then return 
null.

But what is the rationale for returning null?

Surely if 0 is passed in then the unix epoch should be returned?

Similarly, if I have a negative number, should that not return a DateTime from before the unix epoch?

I'm reading in some Java dates at the moment, from MongoDB ObjectIDs, and this behaviour seems a little odd to me.

brian Tue 22 Apr 2014

That design is really to mimic how we map Java APIs that use long to Fantom. By convention Java typically uses a long for date time APIs since their Date/Calendar APIs are such a cluster; and 0 (or a negative) number usually means be not-null which we map to null. Good example is mapping File modified time as Java long to to our DateTime? APIs. I still think that is the best design since that convention is used a ton and DateTimes from 1970 are used rarely.

SlimerDude Tue 29 Apr 2014

I can see how the convention maps well to Java's File.lastModified() but I'm not sure of where else it holds true. fromJava() does seem inconsistent / non-symmetrical to toJava() though, as toJava() returns negative values:

(DateTime.fromJava(1) - 1day).toJava
-86399999

That said, the method names themselves toJava() / fromJava() indicate a leaky abstraction so I'm happy to leave them to their quirky implementations.

But given a lot systems do use the Unix Epoch, how would people feel about adding toUnixEpoch() / fromUnixEpoch() methods or similar?

SlimerDude Wed 30 Apr 2014

In the mean time, for those who need it:

static const DateTime unixEpoch := DateTime.fromJava(1) - 1ms

static DateTime fromUnixEpoch(Int timeInMs) {
    timeInMs > 0
        ? DateTime.fromJava(timeInMs)
        : unixEpoch + Duration(timeInMs * 1000000)
}

You could do away with the ternary and just return unixEpoch + Duration.fromStr("${timeInMs}ms") but I suspect the method is more performant with.

ivan Wed 30 Apr 2014

I'm not a performance freak, but converting millis to/from Str feels a bit awkward :) How about Duration(ms * 1000000)?

SlimerDude Wed 30 Apr 2014

Yup, that works!

Comment and code updated. Thanks!

brian Thu 1 May 2014

Since fromJava already exists in the public API then we probably shouldn't change that. But if we want to support both, then maybe should just another flag to fromJava?

SlimerDude Thu 1 May 2014

Cool, I'd be happy with that!

brian Sat 3 May 2014

I pushed a fix

Login or Signup to reply.