0

I have an Arduino program that connects to a java web server, and I need to synchronize time. But there is a one hour sync problem.

The output of this Java program:

public class Test {
  public static void main(String[] args) {
    java.util.Date d = new java.util.Date(2018-1900, 11-1, 22, 05, 48, 10); // 22th Nov 2018, 05:48:10
    System.out.println(d);

    long t = d.getTime() / 1000;
    System.out.println(t);
  }
}

is

Thu Nov 22 05:48:10 CET 2018
1542862090

Then, I check on https://www.unixtimestamp.com/

Enter a Timestamp: 1542862090 -> Convert -> 
Timestamp Converter: 1542862090 Is equivalent to: 11/22/2018 @ 4:48am (UTC)

Why do I have this one hour difference (05:48 - 4:48)?

In contrast, running an equivalent program in Arduino using this library:

#include <RtcDS3231.h>
void setup() {
  Serial.begin(115200);
  RtcDateTime date = RtcDateTime(2018, 11, 22, 05, 48, 10); // 22th Nov 2018, 05:48:10
  uint32_t t = date.Epoch32Time();
  Serial.println(t);
}

the output is: 1542865690

Then, I check on https://www.unixtimestamp.com/ Enter a Timestamp: 1542865690 -> Convert ->

Timestamp Converter: 1542865690 Is equivalent to: 11/22/2018 @ 5:48am (UTC)

This looks correct.

The problem is that the java web server sends the epoch time (a long number) to arduino, arduino rebuilds the data as follows, and I get one hour difference:

  RtcDateTime date = RtcDateTime(0);
  date2.InitWithEpoch32Time(t);
  Serial.println(date.Hour());   // 4

How I get the correct epoch time in Java, independently of time zone? Or, is the Java result correct, and that arduino library is buggy? What am I missing?

David Portabella
  • 12,390
  • 27
  • 101
  • 182
  • `05:48:10 CET` vs `4:48am (UTC)` CET != UTC – Scary Wombat Nov 22 '18 at 05:55
  • Also as per javadocs https://docs.oracle.com/javase/7/docs/api/java/util/Date.html#Date(int,%20int,%20int,%20int,%20int,%20int) *in the local time zone.* BTW, this is a very deprecated method – Scary Wombat Nov 22 '18 at 05:59
  • Thanks. The problem was that `Date.getTime` (and `System.currentTimeMillis)` return the epoch time using the default system time zone (this was Zurich in my case). That arduino library does not have the concept of time zone (so, it uses the equivalent of `ZoneOffset.UTC`). So we need to explicitly return the time using the `ZoneOffset.UTC`. `long t = java.time.LocalDateTime.now.atZone(java.time.ZoneOffset.UTC).toInstant.toEpochMilli / 1000` – David Portabella Nov 22 '18 at 10:22
  • to rephrase my last comment, my java program was computing epoch time using `ZoneId.systemDefault`, while the arduino library was parsing the epoch time using the equivalent of `ZoneOffset.UTC`. As that arduino library does not handle timezones, my solution is to tell the java program to use also `ZoneOffset.UTC`. `long t = java.time.LocalDateTime.now.atZone(java.time.ZoneOffset.UTC).toInstant.toEpochMilli / 1000` – David Portabella Nov 22 '18 at 10:48
  • Never use `LocalDateTime` for handling moments. Precisely the *wrong* class to use here. – Basil Bourque Nov 22 '18 at 21:13
  • @BasilBourque, ok, thx, you mentioned "what not to use". could you also say "what to use", please? or even to correct this one-line code? – David Portabella Nov 26 '18 at 09:29
  • To get a count of whole seconds since the epoch reference of 1970-01-01T00:00Z: `Instant.now().getEpochSecond()`. Best to transmit that as text in standard ISO 8601 format rather than as a mere ambiguous integer: `Instant.now().truncatedTo( ChronoUnit.SECONDS ).toString()` ➙ `2018-11-26T19:41:48Z`. This has all been discussed many many times already on Stack Overflow. Please search Stack Overflow thoroughly before posting. – Basil Bourque Nov 26 '18 at 19:59
  • See also: [*What's the difference between Instant and LocalDateTime?*](https://stackoverflow.com/q/32437550/642706) – Basil Bourque Nov 26 '18 at 20:00
  • FYI, the terribly troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Nov 26 '18 at 20:03
  • `Instant.now().getEpochSecond()` returns the epoch time using the default system time zone (this was Zurich in my case), so it has the same problem. Instead, the solution I posted returns the epoch time using the ZoneOffset.UTC: `java.time.LocalDateTime.now.atZone(java.time.ZoneOffset.UTC).toInstant.toEpochMilli` – David Portabella Dec 03 '18 at 22:15
  • about the proposition for transmitting the datetime as text, I am using IoT devices, and so I need to optimize the transmission and processing. sending a 64 bit number is more optimal then sending and parsing such a text. – David Portabella Dec 03 '18 at 22:17

1 Answers1

0

That java Date constructor is deprecated and, more important for you, it uses local time. So my guess is your java machine is located one hour away from UTC.

Perdi Estaquel
  • 819
  • 1
  • 6
  • 21