1

I am trying to find out the day light saving start time in US which is 14th March 2021 at 2:00 AM but my code is returning the 14th March 2021 at 3:00 AM. I am not able to understand this one hour time difference. My code is listed below:

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.time.zone.ZoneOffsetTransition;
import java.time.zone.ZoneRules; 
class DST{
public static void main(String[] args) {       
     ZoneId zoneId = ZoneId.of("America/New_York");
     ZoneRules rules = zoneId.getRules();
     ZoneOffsetTransition nextTransition = rules.nextTransition(Instant.now());
     Timestamp ts = Timestamp.valueOf(nextTransition.getInstant().atZone(zoneId).toLocalDateTime());
     SimpleDateFormat sdf = new SimpleDateFormat("MMMM d, yyyy 'at' h:mm a");
     String date = sdf.format(ts);
     system.out.println("DST time:"+ date );
    }
}

The date value is come as March 14, 2021 at 3:00 AM but it should be March 14, 2021 at 2:00 AM. I am not able to understand the difference of one hour time difference?

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
Sumit Sood
  • 441
  • 7
  • 23
  • not sure, but have you tried printing the `ZonedDateTime` returned by `getInstant().atZone(zoneId)` instead of converting it to the `LocalDateTime`? – Hulk Jan 06 '21 at 08:51
  • 2
    @Hulk: It returns `2021-03-14T03:00-04:00[America/New_York]` – Sumit Sood Jan 06 '21 at 08:56
  • 2
    Why are you mixing the old date and time API and the newer one available in the `java.time` package? – MC Emperor Jan 06 '21 at 09:09
  • 1
    But when the transition happens at 2 AM, it means the clock is turned forward to 3, so it *IS* 3 AM at that point in time. You are getting the correct result. – Ole V.V. Jan 06 '21 at 12:04

2 Answers2

3

I think the (unnecessary) conversion to Timestamp is the cause of the error:

import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.zone.ZoneOffsetTransition;
import java.time.zone.ZoneRules;

public class DST {
    public static void main(String[] args) {
        ZoneId zoneId = ZoneId.of("America/New_York");
        ZoneRules rules = zoneId.getRules();
        ZoneOffsetTransition nextTransition = rules.nextTransition(Instant.now());
        DateTimeFormatter sdf = DateTimeFormatter.ofPattern("MMMM d, yyyy 'at' h:mm a");
        System.out.println("DST time:" + nextTransition.getDateTimeBefore().format(sdf));
    }
}

gives you (as expected): March 14, 2021 at 2:00 AM

At this moment in time the time change already occurred, so it's indeed 3AM. That's the reason why API designers had to create the method getDateTimeBefore().

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Benoit
  • 5,118
  • 2
  • 24
  • 43
  • Thanks @Benoit, problem was that I was using `nextTransition.getInstant().atZone(zoneId).toLocalDateTime()` but you are using `nextTransition.getDateTimeBefore()` not sure the difference into both? do you have any idea? – Sumit Sood Jan 06 '21 at 09:18
  • `nextTransition.getDateTimeBefore()` gives the `LocalDateTime`, not `ZondeDateTime`. – Arvind Kumar Avinash Jan 06 '21 at 09:18
  • @SumitSood The problem comes from the use of `TimeStamp` and `SimpleDateFormat` classes, not from `nextTransition.getInstant()`. – Benoit Jan 06 '21 at 09:31
  • @Benoit: I am trying to understand why `nextTransition.getInstant().atZone(zoneId).format(sdf) ` returns `March 14, 2021 at 3:00 AM` – Sumit Sood Jan 06 '21 at 09:43
  • 1
    @SumitSood OK, I get it. Well at this moment in time, the time change already occurred, so it's indeed 3AM. That's the reason why API designers had to create this method `getDateTimeBefore()`. – Benoit Jan 06 '21 at 09:55
  • 3
    It’s certainly `getDateTimeBefore()` making the difference. If you wanted the time before the transition, you should not be very surprised that a method thus named gives it to you. – Ole V.V. Jan 06 '21 at 12:09
2

Check the following information from https://www.timeanddate.com/time/change/usa/new-york

14 Mar 2021 - Daylight Saving Time Starts
When local standard time is about to reach
Sunday, 14 March 2021, 02:00:00 clocks are turned forward 1 hour to
Sunday, 14 March 2021, 03:00:00 local daylight time instead.

The information matches with the output of the following code:

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.time.zone.ZoneOffsetTransition;
import java.time.zone.ZoneRules;
import java.util.Date;

public class Main {
    public static void main(String[] args) {
        ZoneId zoneId = ZoneId.of("America/New_York");

        ZoneRules rules = zoneId.getRules();
        ZonedDateTime zdt = ZonedDateTime.now(zoneId);
        ZoneOffsetTransition nextTransition = rules.nextTransition(zdt.toInstant());

        ZonedDateTime zdtAfterTransition = nextTransition.getInstant().atZone(zoneId);
        ZonedDateTime zdtBeforeTransition = nextTransition.getInstant().minus(1, ChronoUnit.DAYS).atZone(zoneId);
        System.out.println(zdtBeforeTransition);
        System.out.println(zdtAfterTransition);

        LocalDateTime ldtBeforeTransition = nextTransition.getDateTimeBefore();
        System.out.println(ldtBeforeTransition);

        // Convert LocalDateTime to java.sql.Timestamp
        Timestamp ts = new Timestamp(Date.from(ldtBeforeTransition.toInstant(ZoneOffset.UTC)).getTime());
        SimpleDateFormat sdf = new SimpleDateFormat("MMMM d, yyyy 'at' h:mm a");
        String date = sdf.format(ts);
        System.out.println("DST time:" + date);
    }
}

Output:

2021-03-13T02:00-05:00[America/New_York]
2021-03-14T03:00-04:00[America/New_York]
2021-03-14T02:00
DST time:March 14, 2021 at 2:00 am

The date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. The class, java.sql.Timestamp extends java.util.Date and therefore it inherits the same problems. It is recommended to stop using them completely and switch to the modern date-time API.

Learn about the modern date-time API from Trail: Date Time.

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