0

I have a time range for which both the start time and end time are in UTC.

The local time stays the same for all the days in the date range. That is why if the end date is after daylight time saving is over, the UTC date changes by 1 hour. i.e. suppose the start date is 10/23 and end date is 11/11 at 2 AM US/pacific. So the range I have in UTC becomes 10/23 09:00 AM UTC to 11/11 10:00 AM UTC.

I want to get all the dates in the time range in UTC. If I go on adding one day from start date, after day light time saving the UTC time will remain same and that is why the local time will be off by 1 hour. i.e in the above example if I keep adding one day from 10/23 09:00 after day light time saving the date I will receive is (11/03 09:00 UTC), (11/04 09:00 UTC), (11/05 09 UTC) and so on. Which will be 01:00 AM PST. Is there any way in java to get date time within the time range so that till 11/02 I will get "11/02 09:00 UTC" and from 11/03 onwards I will get "11/03 10:00 UTC"?

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.*;
import java.text.SimpleDateFormat;
import java.util.*;

public class MyClass {
    public static void main(String args[]) throws Exception{
      String date1 = "Wed Oct 23 11:30:00 GMT 2019";
      String date2 = "Mon Nov 04 12:30:00 GMT 2019";
      convert(date1, date2);
    }

    private static void convert(String date1, String date2) throws Exception{
        SimpleDateFormat localDateFormat = new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy");

        DateTimeFormatter formatter = DateTimeFormat.forPattern("E MMM dd HH:mm:ss z yyyy");

        DateTime sDate = formatter.parseDateTime(date1);
        DateTime eDate = formatter.parseDateTime(date2);
        while(eDate.isAfter(sDate) || eDate.equals(sDate)) {
            Date finaldate = sDate.toDate();
            System.out.println(localDateFormat.format(finaldate));
            sDate = sDate.plusDays(1);
        }
    }
}

The output for following code is:

Thu Oct 24 11:30:00 GMT 2019
Fri Oct 25 11:30:00 GMT 2019
Sat Oct 26 11:30:00 GMT 2019
Sun Oct 27 11:30:00 GMT 2019
Mon Oct 28 11:30:00 GMT 2019
Tue Oct 29 11:30:00 GMT 2019
Wed Oct 30 11:30:00 GMT 2019
Thu Oct 31 11:30:00 GMT 2019
Fri Nov 01 11:30:00 GMT 2019
Sat Nov 02 11:30:00 GMT 2019
Sun Nov 03 11:30:00 GMT 2019
Mon Nov 04 11:30:00 GMT 2019

But from Nov 03, I am trying to get 12:30 as the time in local timezone stays the same. I am trying to achieve is time so that time in local timezone will be constant. i.e. till Nov 02, 11:30 UTC converts to 4:30 PST. After daylight time saving is over, the time in local time zone will stay the same. So in UTC I am trying to get 12:30 after daylight time saving is over.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
user2803056
  • 377
  • 4
  • 12
  • 1
    Can you write code for us to debug? You tagged your question with [java]. – FailingCoder Oct 23 '19 at 01:27
  • Are you using Joda-Time’s `LocalDate` for your dates? That has got neither time of day nor time zone, so you shouldn’t have the problem you describe. – Ole V.V. Oct 23 '19 at 06:24
  • Possible duplicate of [how to get a list of dates between two dates in java](https://stackoverflow.com/questions/2689379/how-to-get-a-list-of-dates-between-two-dates-in-java) (there are some very good answers there; the best one is [the one by Meno Hochschild](https://stackoverflow.com/questions/2689379/how-to-get-a-list-of-dates-between-two-dates-in-java), it requires Java 9). – Ole V.V. Oct 23 '19 at 06:26
  • I have updated the code which I am trying to write. This is just a test code so please ignore the coding standards. – user2803056 Oct 23 '19 at 20:18
  • You are parsing the date as GMT, then printing it as GMT. GMT does not observe daylight savings time. – Mike Harris Oct 23 '19 at 20:28
  • That makes sense but I am trying to achieve is time so that time in local timezone will be constant. i.e. till Nov 02, 11:30 UTC converts to 4:30 PST. After day light time saving is over the time in local time zone will stay the same. So in UTC I am trying to get 12:30 after day light time saving is over. – user2803056 Oct 23 '19 at 20:49
  • Thank you for your edit, your code, your current output and the explanation of what you want instead. It turned a pretty unclear question into a very clear one. I pasted essential information from your last comment into the question itself for you so we have everything in one place, it’s a lot nicer. – Ole V.V. Oct 24 '19 at 07:12
  • Thank you so much for help. – user2803056 Oct 24 '19 at 22:48

1 Answers1

0

ZonedDateTime from java.time

I think that the elegant solution uses java.time, the modern Java date and time API. You may think of it as the successor of the Joda-Time library that you were using. What we need is the ZonedDateTime class from java.time.

    ZoneId zone = ZoneId.of("America/Los_Angeles");
    DateTimeFormatter formatter = DateTimeFormatter
            .ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ROOT);

    String date1 = "Wed Oct 23 11:30:00 GMT 2019";
    String date2 = "Mon Nov 04 12:30:00 GMT 2019";

    ZonedDateTime startDateTime = ZonedDateTime.parse(date1, formatter)
            .withZoneSameInstant(zone);
    ZonedDateTime endDateTime = ZonedDateTime.parse(date2, formatter)
            .withZoneSameInstant(zone);
    while (! startDateTime.isAfter(endDateTime)) {
        Instant gmt = startDateTime.toInstant();
        System.out.println(startDateTime + "  GMT: " + gmt);
        startDateTime = startDateTime.plusDays(1);
    }

Output from this snippet is:

2019-10-23T04:30-07:00[America/Los_Angeles]  GMT: 2019-10-23T11:30:00Z
2019-10-24T04:30-07:00[America/Los_Angeles]  GMT: 2019-10-24T11:30:00Z
2019-10-25T04:30-07:00[America/Los_Angeles]  GMT: 2019-10-25T11:30:00Z
… (cut) …
2019-11-01T04:30-07:00[America/Los_Angeles]  GMT: 2019-11-01T11:30:00Z
2019-11-02T04:30-07:00[America/Los_Angeles]  GMT: 2019-11-02T11:30:00Z
2019-11-03T04:30-08:00[America/Los_Angeles]  GMT: 2019-11-03T12:30:00Z
2019-11-04T04:30-08:00[America/Los_Angeles]  GMT: 2019-11-04T12:30:00Z

You see that the GMT times change from 11:30 to 12:30 from 3rd November.

If you want output formatted as in your question:

    ZoneId gmtZone = ZoneId.of("Etc/GMT");
    while (! startDateTime.isAfter(endDateTime)) {
        ZonedDateTime gmtTime = startDateTime.withZoneSameInstant(gmtZone);
        System.out.println(gmtTime.format(formatter));
        startDateTime = startDateTime.plusDays(1);
    }
Wed Oct 23 11:30:00 GMT 2019
Thu Oct 24 11:30:00 GMT 2019
… (cut) …
Sun Nov 03 12:30:00 GMT 2019
Mon Nov 04 12:30:00 GMT 2019

Joda-Time

I am hesitating to present a Joda-Time solution for two reasons. One, the Joda-Time project is in maintenance mode, and for new code you should prefer java.time. Two, I am not well versed in Joda-Time, so my solution may not be the most elegant possible. I have found no Joda-Time equivalent of ZonedDateTime, so I am using its LocalDateTime, which both requires a few more conversions and is more fragile because the datetime object doesn’t know its own time zone.

    DateTimeZone.setDefault(DateTimeZone.forID("Etc/GMT"));

    DateTimeZone zone = DateTimeZone.forID("America/Los_Angeles");
    DateTimeZone gmtZone = DateTimeZone.forID("Etc/GMT");
    DateTimeFormatter formatter
            = DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss zzz yyyy")
                    .withLocale(Locale.ROOT);

    String date1 = "Wed Oct 23 11:30:00 GMT 2019";
    String date2 = "Mon Nov 04 12:30:00 GMT 2019";

    LocalDateTime sDate = formatter.parseDateTime(date1)
            .withZone(zone)
            .toLocalDateTime();
    LocalDateTime eDate = formatter.parseDateTime(date2)
            .withZone(zone)
            .toLocalDateTime();
    while(eDate.isAfter(sDate) || eDate.equals(sDate)) {
        DateTime finaldate = sDate.toDateTime(zone).withZone(gmtZone);
        System.out.println(finaldate.toString(formatter));
        sDate = sDate.plusDays(1);
    }
Wed Oct 23 11:30:00 GMT 2019
Thu Oct 24 11:30:00 GMT 2019
… (cut) …
Sat Nov 02 11:30:00 GMT 2019
Sun Nov 03 12:30:00 GMT 2019
Mon Nov 04 12:30:00 GMT 2019

Under all circumstances avoid the poorly designed and long outdated Date and SimpleDateFormat classes. The only exception is if you need an old-fashioned Date object for a legacy API that you cannot afford to upgrade just now. In this case convert just before calling into that legacy API.

Link

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