0

How do I get a string in Java in ISO8601 given the number of seconds since the epoch? I'm having trouble finding it anywhere.

I want the format to look something like this: 2000-06-31T19:22:15Z

Using just Date d = new Date(# of milliseconds from my # of seconds) gives me a date in 1970 when I should be getting something in 2000.

curious4cs
  • 193
  • 1
  • 3
  • 14
  • 2
    Show us exactly what you used to get the number of milliseconds from seconds. – Elliott Frisch Dec 31 '17 at 03:42
  • 1
    The `DateTimeFormatter` has built in support for `ISO8601` - you just need to convert the time from seconds to milliseconds, wrap in a `LocalDateTime` – MadProgrammer Dec 31 '17 at 03:49
  • 1
    The best way to get a good answer fast is to search before asking. You are asking 2 questions in 1, and each has ben asked and answered many times. (1) How to convert seconds since eopch? See for exampe [Convert Epoch seconds to date and time format in Java](https://stackoverflow.com/questions/8262333/convert-epoch-seconds-to-date-and-time-format-in-java). (2) How to format into ISO-8601? See for example [How to get current moment in ISO 8601 format with date, hour, and minute?](https://stackoverflow.com/questions/3914404/how-to-get-current-moment-in-iso-8601-format-with-date-hour-and-minute) – Ole V.V. Dec 31 '17 at 06:41

3 Answers3

4

tl;dr

Instant.ofEpochSeconds( 962_392_935L )  // Convert from a count of whole seconds since 1970-01-01T00:00Z.
       .toString()                      // Generate a string in standard ISO 8601 format.

2000-06-30T19:22:15Z

Details

The other Answers are needlessly complicated.

The Instant class represents a point on the timeline in UTC with a resolution of nanoseconds.

Instant.now()  // Current moment in UTC.

If you have a count of seconds since the epoch reference date of the first moment of 1970 in UTC, 1970-01-01T00:00Z, then simply use the Instant.ofEpochSecond factory method.

Instant instant = Instant.ofEpochSeconds( mySeconds ) ;

To generate a String in standard ISO format, simply call Instant::toString.

String output = instant.toString() ;

2000-06-30T19:22:15Z

To go the other direction, while correcting your example’s June 31st error to June 30th as pointed out by Elliott Frisch:

long secondsSinceEpoch = Instant.parse( "2000-06-30T19:22:15Z" ).toEpochSecond() ;  // Gets the number of seconds from the Java epoch of 1970-01-01T00:00:00Z.

962392935

Avoid legacy date-time classes always

Do not use the troublesome old date-time classes such as Date. They are supplanted entirely by the java.time classes built into Java 8 and later.

Avoid LocalDateTime for your purpose

The suggestions seen elsewhere on this page to use the LocalDateTime class are ill-advised.

That class purposely lacks any concept of time zone or offset-from-UTC. As such, this class does not represent a specific point on the timeline. You would be discarding the vital information about your value being in UTC.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Thanks, this is better if you don't need to customize the format too much it seems whereas the other answer does – curious4cs Dec 31 '17 at 20:20
  • 1
    @curious4cs You asked for `2000-06-31T19:22:15Z` which is exactly what is rendered by the code shown in this Answer, using [`Instant::toString`](https://docs.oracle.com/javase/9/docs/api/java/time/Instant.html#toString--). If you wanted other formats you should have specified so in your Question. – Basil Bourque Dec 31 '17 at 21:08
1

The main problem you are probably having, is that June 2000 only had 30 days. That being said instead of using Date, you could use a LocalDateTime with LocalDateTime.ofEpochSecond(long, int, ZoneOffset) like

long epochSecond = 962392935L;
int nanoOfSecond = 0;
ZoneOffset offset = ZoneOffset.UTC;
LocalDateTime ldt = LocalDateTime.ofEpochSecond(epochSecond, nanoOfSecond, offset);
System.out.println(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'").format(ldt));

Which should be all you need to see

2000-06-30T19:22:15Z

which is like your requested output.

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
0
    Instant start = Instant.now() ;
    Instant stop = start.plusSeconds( 135L ) ;

    Duration d = Duration.between( start , stop ) ;

    long minutesPart = d.toMinutes(); 
    long secondsPart = d.minusMinutes( minutesPart ).getSeconds() ;

    System.out.println( "Interval: " + start + "/" + stop );
    );

I think this piece of code will help you in getting something like this: 2000-06-31T19:22:15Z.

prasad
  • 26
  • 5
  • You're just relying on the internal representation of the `Instant` field, which may not be reliable over time - better to make use the `DateTimeFormatter` class – MadProgrammer Dec 31 '17 at 03:57
  • 1
    I didn’t get that, @MadProgrammer? [`Instant.toString()`](https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#toString--) is documented to produce “A string representation of this instant using ISO-8601 representation.”, it’s not internal representation. The code does a few things not asked for in the question, though. – Ole V.V. Dec 31 '17 at 06:52
  • Yes, technically that is correct, but I still think that a DateTimeFormatter (either using one of the predefined instances or custom instance) would be a more useful and reliable solution - that’s just my opinion – MadProgrammer Dec 31 '17 at 06:54