69

Java 8 has a whole new library for dates and times in the package java.time which is very welcome thing to anyone who has had to use JodaTime before or hassle with making it's own date processing helper methods. Many classes in this package represent timestamps and have helper methods like getHour() to get hours from timestamp, getMinute() to get minutes from timestamp, getNano() to get nanos from timestamp etc...

I noticed that they don't have a method called getMillis() to get the millis of the time stamp. Instead one would have to call method get(ChronoField.MILLI_OF_SECOND). To me it seems like an inconsistency in the library. Does anyone know why such a method is missing, or as Java 8 is still in development is there a possibility that it will be added later?

https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html

The classes defined here represent the principal date-time concepts, including instants, durations, dates, times, time-zones and periods. They are based on the ISO calendar system, which is the de facto world calendar following the proleptic Gregorian rules. All the classes are immutable and thread-safe.

Each date time instance is composed of fields that are conveniently made available by the APIs. For lower level access to the fields refer to the java.time.temporal package. Each class includes support for printing and parsing all manner of dates and times. Refer to the java.time.format package for customization options...

Example of this kind of class:
https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html

A date-time without a time-zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30.

LocalDateTime is an immutable date-time object that represents a date-time, often viewed as year-month-day-hour-minute-second. Other date and time fields, such as day-of-year, day-of-week and week-of-year, can also be accessed. Time is represented to nanosecond precision. For example, the value "2nd October 2007 at 13:45.30.123456789" can be stored in a LocalDateTime...

5
  • Seems as if they wanted to use polymorphism to resolve a bunch of methods all called get(), rather than giving them individual, unique names. If it bothers you, write a class that inherits the original class, and put your own getMillis() method in the new class. Jan 24, 2014 at 23:13
  • @RobertHarvey Most classes in the java.time package are immutable and can't be extended.
    – assylias
    Jan 25, 2014 at 8:59
  • 2
    @RobertHarvey The question for me is not how can I solve this. It just seamed a weird inconsistency and I wondered if there is an interesting explanation for this.
    – Tarmo
    Jan 25, 2014 at 14:54
  • I have the idea that some architectures/OS's don't reliably support milliseconds. In other words, the system time can't be retrieved to the millisecond, only to the centi- or decisecond.
    – Marco
    Jan 28, 2014 at 23:54
  • See stackoverflow.com/a/23945792/40064 on a way to do it via the Instant class Mar 17, 2016 at 11:01

3 Answers 3

65
+50

JSR-310 is based on nanoseconds, not milliseconds. As such, the minimal set of sensible methods are based on hour, minutes, second and nanosecond. The decision to have a nanosecond base was one of the original decisions of the project, and one that I strongly believe to be correct.

Adding a method for millis would overlap that of nanosecond is a non-obvious way. Users would have to think about whether the nano field was nano-of-second or nano-of-milli for example. Adding a confusing additional method is not desirable, so the method was omitted. As pointed out, the alternative get(MILLI_OF_SECOND) is available.

FWIW, I would oppose adding the getMillis() method in the future.

4
  • 1
    I have gotten some very good answers to this question but your answer is my favourite as it is short and yet it still makes a very good point and truely convinces me in the necessity of this approach. Thank you.
    – Tarmo
    Feb 4, 2014 at 8:37
  • 13
    @s3ib if you check answerer's profile, you'll also notice that he is a specification lead for the very API you are asking about. This makes an answer as authoritative as it gets doesn't it :)
    – gnat
    Feb 4, 2014 at 11:01
  • So having to do instant.getEpochSecond * 1000 + instant.getNano / 1000000 is reasonable boilerplate to be able to communicate with legacy (at this point, all) Java APIs, Javascript, etc?
    – nilskp
    Mar 24, 2014 at 17:40
  • 11
    no, in that case you can just use instant.toEpochMilli() download.java.net/jdk8/docs/api/java/time/… Mar 25, 2014 at 0:22
20

Before being part of openJDK, threeten was on github and before that it was on sourceforge. Back then, Stephen Colebourne, who is a specification lead on jsr-310, made a survey tha you can still find on the sourceforge site.

The fourth question on the survey covered the method names for LocalTime:
1) getHourOfDay(), getMinuteOfHour(), getSecondOfMinute(), getNanoOfSecond()
2) getHour(), getMinute(), getSecond(), getNanoOfSecond()
3) getHour(), getMinute(), getSecond(), getNano()
4) another idea

only 6.23% chose answer #4 and among them approximately 15% asked for a getMillis(), i.e. less than 1% of the total votes.

That is probably why there was no getMillis in the first place and I could not find anything related on the openjdk mailing list so the matter was apparently not discussed afterwards.

4
  • 3
    I think that giving people several choices makes it more likely that they pick one of those choices, even if their ideal choice is under "other". I could be wrong, though. Jan 30, 2014 at 20:29
  • 2
    @AllonGuralnek Yes definitely - however the milliseconds component was important in the Date API because everything was based on a number of millis since the epoch. In the new API it is less relevant IMO. In most use cases, you either need a second precision or the best precision available (nanos). I may be wrong.
    – assylias
    Jan 30, 2014 at 20:41
  • 1
    This seems to ask about naming of methods, not which methods should exist.
    – svick
    Jan 31, 2014 at 20:27
  • 1
    Right, sorry, I wasn't clear: I meant the question from the survey, that it doesn't seek directly related to this question.
    – svick
    Feb 1, 2014 at 0:33
16

The classes that represent unambiguous UTC times (those are Instant, OffsetDateTime, ZonedDateTime) have two helper methods for accessing the absolute offset from the Java epoch, i.e. what you call 'millisecond time' in the java.util.Date, which you could use to get at milliseconds

long getEpochSecond()
int getNano()

1000L*getEpochSecond() + getNano() / 1000000L;

Some reasons as to why this has been chosen instead of long getEpochMillis() were discussed on the jsr 310 mailing list, some of which I've extracted for convenience:

it seems reasonable to suppose that milliseconds precision won't be sufficient. However, anything greater than nanosecond precision seems excessive

...

In order to implement this, my preferred option would be 64 bit long seconds (signed) + 32 bit int nanoseconds (unsigned).

...

I prefer the split to be at the second level as that is the official SI unit of time in science, and the most universally agreed standard.

Splitting at the days level is problematic for instants as it doesn't handle leap seconds. Splitting at the milliseconds level, while integrating slightly better with the rest of Java, seems really rather odd. Plus it loses in the supported range.

Splitting at the second as proposed, gives a range of instants of nanoseconds over 290 billion years. While nobody should ever use that precision over that range of the time-line, I'd suggest its easier to support it than to block it.splitting at the days level is problematic for instants as it doesn't handle leap seconds

I have a feeling that another reason was to intentionally make it hard to convert from java.util.Date to JSR310 classes, hoping that developers would try to understand the differences between the various options and not just blindly (mis)use the new classes.

As to why the LocalDateTime class doesn't have those methods - they can't possibly exist there because LocalDateTime is not tied to the UTC timeline until you decide which zone you're in or what your UTC offset is, at which point you have yourself an OffsetDateTime or ZonedDateTime (both of which have the needed methods).

Alternatively, you could define you own LOCAL_EPOCH constant to 1970-01-01T00:00:00 and then do a MILLIS.between(LOCAL_EPOCH, localTime) to get some sort of duration in milliseconds. This value, however, will not be compatible with any value returned by System.currentTimeMilliseconds() or java.util.Date.getTime(), unless of course you define your local time to be UTC time; but in this case you might as well use Instant directly or OffsetDateTime with ZoneOffset.UTC.

4
  • 4
    "they can't possibly exist there because LocalDateTime is not tied to the UTC timeline" => a LocalDateTime could certainly have a getMillis method that would basically return getNanos()/1e6 - the fact that it is not an instant in time does not prevent it from having a millisecond component.
    – assylias
    Jan 28, 2014 at 8:13
  • 2
    "I have a feeling that another reason was to intentionally make it hard to convert from java.util.Date to JSR310 classes" Probably true, but unfortunately "millis since epoch" has become an almost universal representation of time, so for anything that needs to communicate with older Java APIs, Javascript, anything else, this omission is a real hassle.
    – nilskp
    Mar 24, 2014 at 17:31
  • Your code snippet at the top is incorrect - you need to multiply the getEpochSecond by 1000.
    – Tin Wizard
    Jun 8, 2016 at 16:12
  • @nilskp They're two different things. Question is asking about getMillis() as in getMillis-of-second; you're talking about "millis since epoch". The former is absent as explained in the accepted answer. The latter is already available as Instant.toEpochMillis(). So, for a LocalDateTime, you'd go: ldt.toInstant(offset).toEpochMillis()
    – SusanW
    Mar 8, 2017 at 18:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.