3

My Android app communicate with an API which give me the following timestamp : -2209161600. Converted to a date time, it's supposed to be 12-30-1899 00:00:00

The problem is, I tried to convert this timestamp using both the default library, threetenbp, and then jodatime, but I always get the same wrong result, using Europe/Paris timezone : 12-30-1899 00:09:21

Why does that happen ?

EDIT: For example with jodatime

DateTime dt = new DateTime(-2209161600000L, DateTimeZone.forID("Europe/Paris")); // dt: "1899-12-30T00:09:21.000+00:09:21"
Bencri
  • 1,173
  • 1
  • 7
  • 22
  • Could you show us how you converted this timestamp? – deHaar Aug 02 '19 at 12:52
  • 1
    Why do you think `-2209161600` should beceome `12-30-1899 00:00:00`? I'm not saying you are wrong, I am asking the basis on which you believe that. – Andy Turner Aug 02 '19 at 12:53
  • @AndyTurner because that's the date that was set on the server side, which the API send me in the form of a timestamp. Also, I tried websites like https://www.epochconverter.com/ and got the exact same result. Only my application give me the wrong date. – Bencri Aug 02 '19 at 13:04
  • @deHaar I added a short example with joda date api – Bencri Aug 02 '19 at 13:05
  • The other way round seems to work: `LocalDateTime ldt = LocalDateTime.parse("12-30-1899 00:00:00", DateTimeFormatter.ofPattern("MM-dd-yyyy HH:mm:ss"));` and then `System.out.println(ldt.toInstant(ZoneOffset.UTC).toEpochMilli());` results in the output `-2209161600000` (using `java.time`). – deHaar Aug 02 '19 at 13:08
  • just to start with old java `System.out.println(new Date(-2209161600L * 1000L))` prints `Sat Dec 30 00:00:00 UTC 1899` a bit more actual `System.out.println(LocalDateTime.ofEpochSecond(-2209161600L, 0, ZoneOffset.UTC));` prints `1899-12-30T00:00` – user85421 Aug 02 '19 at 13:22
  • 1
    @deHaar I think the key point in your code is ZoneOffset.UTC – Bencri Aug 02 '19 at 13:24
  • maybe but `09:21` is not the offset of Madrid,....strange is passing the number as a string... but I do not use Jodatime....better use `Instant.ofEpochSecond(-2209161600L)` – user85421 Aug 02 '19 at 13:28
  • @CarlosHeuberger no I switched to Europe/Paris to see if I still had the same problem – Bencri Aug 02 '19 at 13:30
  • no, you are still using String, here: `...DateTime("-2209161600000",...` I do not know what Jodatime thinks that text is... – user85421 Aug 02 '19 at 13:31
  • It's just a copy/paste fail, I edited the post. – Bencri Aug 02 '19 at 13:36
  • 2
    *In 1884, the international community adopted Greenwich Mean Time (GMT) as the world's time standard. Back then, GMT was based on solar time at the prime meridian that runs through Greenwich, United Kingdom.However, France continued to use its own standard for several decades. It was based on solar time in Paris, so local time in France was Paris Mean Time (PMT), which was **9 minutes and 11 seconds** ahead of GMT* - [source](https://www.timeanddate.com/time/zone/france). – M. Prokhorov Aug 02 '19 at 14:48

2 Answers2

2

I think I found the answer on the FAQ as part of Why is the offset for a time-zone different to the JDK?:

... affects date-times before the modern time-zone system was introduced. The time-zone data is obtained from the time-zone database. The database contains information on "Local Mean Time" (LMT) which is the local time that would have been observed at the location following the Sun's movements.

Joda-Time uses the LMT information for all times prior to the first time-zone offset being chosen in a location. ...

In other words, the database does not have entries for that time so it is uses the Local Mean Time (e.g. 0:09:21 for Paris, or -0:14:44 for Madrid 1).

System.out.println(new DateTime(-2209161600000L, DateTimeZone.forID("Europe/Paris")));
System.out.println(new DateTime(-2209161600000L, DateTimeZone.forID("Europe/Madrid")));

will print

1899-12-30T00:09:21.000+00:09:21
1899-12-29T23:45:16.000-00:14:44

Solution: depends what tis time is needed for, if UTC is sufficient, use

new DateTime(-2209161600000L, DateTimeZone.forID("UTC"))  // 1899-12-30T00:00:00.000Z

or just the standard java.time classes like

Instant.ofEpochSecond(-2209161600L)
Instant.ofEpochMilli(-2209161600000L)

1 - http://home.kpn.nl/vanadovv/time/TZworld.html#eur

user85421
  • 28,957
  • 10
  • 64
  • 87
1

Carlos Heuberger may have said it already. As far as I can see, it’s a matter of using UTC instead of Europe/Paris time zone.

    long unixTimestamp = -2_209_161_600L;
    Instant inst = Instant.ofEpochSecond(unixTimestamp);
    System.out.println("As Instant: " + inst);

Output is:

As Instant: 1899-12-30T00:00:00Z

If you need date and time:

    OffsetDateTime dateTime = inst.atOffset(ZoneOffset.UTC);
    System.out.println("As OffsetDateTime: " + dateTime);

As OffsetDateTime: 1899-12-30T00:00Z

Am I missing something?

Explanation

Why does it matter? Because in 1899 Paris used the local mean time in Paris, which is at offset +00:09:21 from UTC. Therefore the correct and expected result in Europe/Paris time zone is the one you got, 12-30-1899 00:09:21. To check this offset: Go to Time Zone in Paris, Île-de-France, France. In the Time zone changes for dropdown choose 1850 – 1899. You will see that the offset of +00:09:21 was in effect during this entire interval if years (both before and after the change of time zone abbreviation in 1891).

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