High accuracy time syncing between Android (Java) and .NET DateTime?

I need a high accuracy time conversion between a native Android app and a .NET-based time stamp.

The .NET side simply uses:

long timeNowTicks = System.DateTime.UtcNow.Ticks;

And I need to match this .NET time stamp to within 5 minutes (3 billion ticks) on the Android side. I can't change the .NET stuff.

I tried:

GregorianCalendar oldUtcTime = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
GregorianCalendar nowUtcTime = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
oldUtcTime.set(1,1,1,0,0,0); // .NET epoch
long utcTicks = 10000 * (nowUtcTime.getTimeInMillis() - oldUtcTime.getTimeInMillis()); // 10,000 ticks per ms

But this consistently gives me a number that is about 2.5 million seconds (~20 days) behind the DateTime.UtcNow.Ticks.

Some people are saying that this is because even though DateTime claims to adhere to the Gregorian Calendar, they don't actually skip the 10 days the Pope added to the calendar to fix it in the 1500's, but nowhere have I found a catch-all, formula-like conversion between the two.

How do I get ~5 minute accuracy between native Android time and .NET DateTime?

Jon Skeet
people
quotationmark

Yes, I believe GregorianCalendar does indeed observe the Julian/Gregorian cutover - although I note that you're setting oldUtcTime to the 1st of February in 1AD, which is probably why you're seeing a difference of 20 days instead of 10 days.

The simplest way to do this is to find out the Unix epoch in milliseconds using .NET - and then use that as a constant on the Java side:

// Handy method in .NET 4.6...
var unixEpoch = DateTimeOffset.FromUnixTimeSeconds(0);
Console.WriteLine(unixEpoch.Ticks / 10000L);

That gives an output of 62135596800000. So then you need:

private static final long BCL_MILLISECONDS_AT_UNIX_EPOCH = 62135596800000L;
private static final long TICKS_PER_MILLISECOND = 10000L;
...

long bclMillis = System.currentTimeMillis() + BCL_MILLISECONDS_AT_UNIX_EPOCH;
long bclTicks = TICKS_PER_MILLISECOND * bclMillis;

Note that this isn't really "high accuracy" - it's only going to be as accurate as the system clock on each side. For really accurate time you'd need to use NTP or something similar. You could still find the two clocks are out by more than 5 minutes, just because clocks drift over time if they're not automatically corrected...

people

See more on this question at Stackoverflow