1

I found this code:

long timeStampSeconds = ChronoUnit.MICROS.between(Instant.EPOCH, Instant.now());

but when I converted this back to fetch month and year using the following code, it gives the wrong output.

try {
    epochLong = Long.parseLong(epoch);
} catch (RuntimeException e) {
    //Log exception
    return null;
}

Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(epochLong);
String month = String.valueOf(cal.get(Calendar.MONTH));
String year = String.valueOf(cal.get(Calendar.YEAR));
//print month and year

Any pointers as to how I can generate this in microseconds and get the month and year back right? Please help.

Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
  • 3
    what is "the wrong output"? – f1sh Nov 18 '19 at 10:13
  • I always see epoch getting generated with 3 zeroes at the end, can this be avoided? – Samayra Goyal Nov 18 '19 at 10:16
  • 1
    Give and example of: -your input, -what you get, -what you expect to get – jhamon Nov 18 '19 at 10:17
  • Wrong output is: From epoch like 1574072161043000 expected month is 10 and year 2019 but i get month as 4 and year as 51850 which is absurd – Samayra Goyal Nov 18 '19 at 10:17
  • 1
    `setTimeInMillis` and `ChronoUnit.MICROS.between`, maybe millis and micros mismatch... maybe the is another [ChronoUnit](https://docs.oracle.com/javase/8/docs/api/java/time/temporal/ChronoUnit.html#MILLIS) that would get a better fit – jhamon Nov 18 '19 at 10:19
  • I want to generate in micros only. This is the usecase, but how to I get back month and year? Calendar has setTimeInMillis only – Samayra Goyal Nov 18 '19 at 10:20
  • 1
    convert micros to milli? hint: it's a division – jhamon Nov 18 '19 at 10:20
  • 2
    the difference between `ChronoUnit.MICROS` and `setTimeInMillis` should ring a bell. – f1sh Nov 18 '19 at 10:22
  • But the micros also is not generating the precision.. The last 3 digits are zero, first of all how do I get the last 3 precision bits also.. and then how do I set? (If I divide I loose them again) – Samayra Goyal Nov 18 '19 at 10:22
  • What about `ChronoUnit.MILLIS.between(Instant.EPOCH, Instant.now())`? **MILLIS**... I just used that and it gave me the correct month and year... By the way, I was using `java.time` only. – deHaar Nov 18 '19 at 10:26
  • Thanks but My requirement is that I need to first convert to micros only – Samayra Goyal Nov 18 '19 at 10:29
  • 1
    Please don't use `Calendar` it is legacy now – Youcef LAIDANI Nov 18 '19 at 10:43
  • Possible duplicate of [Java 8 LocalDateTime.now() only giving precision of milliseconds](https://stackoverflow.com/questions/39586311/java-8-localdatetime-now-only-giving-precision-of-milliseconds) – Ole V.V. Nov 19 '19 at 20:56

2 Answers2

2

If you are using java.time from Java-8 you can use :

long timeStampSeconds = ChronoUnit.MICROS.between(Instant.EPOCH, Instant.now());

to back you can convert this to an instant, then the instant to the ZoneDateTime

Instant inst = Instant.EPOCH.plus(timeStampSeconds, TimeUnit.MICROSECONDS.toChronoUnit());
ZonedDateTime zdt = inst.atZone(ZoneId.of("Europe/Paris"));

Then you can get the month, year, day, hour, ...

Month month = zdt.getMonth();
int year = zdt.getYear();

Outputs

MICROS:       1574073141066090
ZoneDateTime: 2019-11-18T11:32:21.066090+01:00[Europe/Paris]
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
2

It depends on the platform and the Java version.

On my Mac example timeStampSeconds values from your code include

  • using jdk-1.8.0_121: 1574193249064000 and 1574193338130000; so always ending in 000
  • using jdk-9.0.4: 1574193430428678 and 1574193438362321; so usually not ending in 000.

On Java 8 the now methods of the java.time classes haven’t got any finer granularity than millisenods, so the microsecond of millisecond will always be 000. On Java 9 a finer granularity is available if the platform supports it, which may not be the case for all platforms.

So if you’re getting 000 always, the solution is to upgrade at least to Java 9 and run your Java program on a computer that supports microsecond precision.

Don’t use Calendar

The Calendar class is poorly designed and long outdated. Also it never supports any unit finer than milliseconds. To convert your microsecond value back to a date and time object, use for example:

    long timeStampSeconds = 1_574_193_438_362_321L;
    Instant convertedBack = Instant.EPOCH.plus(timeStampSeconds, ChronoUnit.MICROS);
    System.out.println(convertedBack);

2019-11-19T19:57:18.362321Z

You will notice that the full microsecond precision is preserved. YCF_L in another answer has already shown how to get the year and month values.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161