2

I have the following piece of code. I'm trying to get the epoch value t for exactly 10 days ago, at the current time. But when I convert t back to a date/time using https://www.epochconverter.com/, the printed result's time is not correct. What am I missing?

        long t = LocalDateTime.now()
                .minusDays(10)
                .toEpochSecond(ZoneOffset.UTC) * 1000;


        System.out.println(t);
S.Dan
  • 1,826
  • 5
  • 28
  • 55
  • 1
    As I understand it, you're taking your "local date/time" at you current time zone subtracting 10 days and then outputting in UTC time zone. What you need to be aware of is, this won't convert the value to UTC, it will just take the "current time" and make appear as UTC, so if it's 6pm local time, it will be 6pm UTC time. Instead, you should be using either ZonedDateTime or converting the epoch seconds using your current time zone – MadProgrammer Sep 21 '21 at 09:00
  • 10 days ago in UTC or 10 days ago in your time zone? In corner cases those two may not be the same point in time. – Ole V.V. Sep 21 '21 at 20:18

2 Answers2

4

So LocalDateTime is a representation of time in your current timezone, you then get the seconds from epoch in the UTC time zone. But what this doesn't do, is convert the time to UTC, it stays unchanged, so if it's 6pm local time, this will generate a time of 6pm UTC.

What you need to do is take into account the timezone. Each of the following statements will print the same value (in seconds) and when I plug them into https://www.epochconverter.com, they give the correct "local time" for when they were generated.

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.TimeZone;

public class Test {

    public static void main(String[] args) {
        TimeZone tz = TimeZone.getDefault();
        ZoneOffset offset = tz.toZoneId().getRules().getStandardOffset(Instant.now());
        long t = LocalDateTime.now()
                .minusDays(10)
                .toEpochSecond(offset);
        System.out.println(t);
        System.out.println(ZonedDateTime.now().minusDays(10).toEpochSecond());
        System.out.println(OffsetDateTime.now(ZoneOffset.UTC).minusDays(10).toEpochSecond());
    }
}

There's probably a few more ways to do this, but these were my basic approaches.

So, for example, I got an output of 1631350948 and when I plugged it into the convert, it printed

GMT: Saturday, 11 September 2021 9:02:28 AM
Your time zone: Saturday, 11 September 2021 7:02:28 PM GMT+10:00
Relative: 10 days ago

The "local time" is correct for when I sampled the output

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
3

I suggest you use OffsetDateTime.now(ZoneOffset.UTC) to get the current Date-Time in UTC and then subtract 10 days from it. Finally, get the epoch seconds from the resulting OffsetDateTime.

import java.time.OffsetDateTime;
import java.time.ZoneOffset;

public class Main {
    public static void main(String[] args) {
        System.out.println(OffsetDateTime.now(ZoneOffset.UTC).minusDays(10).toEpochSecond());
    }
}

Output:

1631350741

ONLINE DEMO

Learn more about the modern Date-Time API* from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110