How to Tackle Daylight Savings Using Timezone in Java

How to tackle daylight savings using TimeZone in Java

This is the problem to start with:

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));

The 3-letter abbreviations should be wholeheartedly avoided in favour of TZDB zone IDs. EST is Eastern Standard Time - and Standard time never observes DST; it's not really a full time zone name. It's the name used for part of a time zone. (Unfortunately I haven't come across a good term for this "half time zone" concept.)

You want a full time zone name. For example, America/New_York is in the Eastern time zone:

TimeZone zone = TimeZone.getTimeZone("America/New_York");
DateFormat format = DateFormat.getDateTimeInstance();
format.setTimeZone(zone);

System.out.println(format.format(new Date()));

Handle Java daylight saving based on different time zone from UTC (joda Interval)

I assume that you need to create intervals of different size for special cases that daylight saving is happening.

I suggest to get the offset of start time and end time and based on the values you can decide if you need to shift your end date or not.

public static void main(String[] args) {
DateTimeZone EDT = DateTimeZone.forID("America/Toronto");
DateTime start = new DateTime(2016, 5, 15, 4, 0, DateTimeZone.UTC);
DateTime end = start.plusDays(2);

int offset1 = (int) TimeUnit.MILLISECONDS.toMinutes(EDT.getOffset(start.getMillis()));
int offset2 = (int) TimeUnit.MILLISECONDS.toMinutes(EDT.getOffset(end.getMillis()));
if (offset1 != offset2) {
end = end.plusMinutes(offset1 - offset2);
}

System.out.println(new Interval(start.toDateTime().withZone(EDT),
end.toDateTime().withZone(EDT)));

}

How to handle daylight saving time properly in Java 7 without Joda Time?

There seems to be a few questions about time zones and daylight savings in Turkey today.

This is likely because Turkey has changed the date for the daylight savings switch from November 1 to November 8.

The timezone data in your JVM may not be current with the change. Oracle has an update for their JVM.

The timezone data updater that you download from the link above is an executable jar file. To update your JVM on a unix host:

sudo java -jar tzupdater.jar --update --location http://www.iana.org/time-zones/repository/tzdata-latest.tar.gz

The tool doesn't seem to output anything on updates, so to verify run:

java -jar tzupdater.jar --version 

The version of the timezone data with the Turkey update is tzdata2015g

Get Daylight Saving Transition Dates For Time Zones in Java

Joda Time (as ever) makes this really easy due to the DateTimeZone.nextTransition method. For example:

import org.joda.time.*;
import org.joda.time.format.*;

public class Test
{
public static void main(String[] args)
{
DateTimeZone zone = DateTimeZone.forID("Europe/London");
DateTimeFormatter format = DateTimeFormat.mediumDateTime();

long current = System.currentTimeMillis();
for (int i=0; i < 100; i++)
{
long next = zone.nextTransition(current);
if (current == next)
{
break;
}
System.out.println (format.print(next) + " Into DST? "
+ !zone.isStandardOffset(next));
current = next;
}
}
}

Output:


25-Oct-2009 01:00:00 Into DST? false
28-Mar-2010 02:00:00 Into DST? true
31-Oct-2010 01:00:00 Into DST? false
27-Mar-2011 02:00:00 Into DST? true
30-Oct-2011 01:00:00 Into DST? false
25-Mar-2012 02:00:00 Into DST? true
28-Oct-2012 01:00:00 Into DST? false
31-Mar-2013 02:00:00 Into DST? true
27-Oct-2013 01:00:00 Into DST? false
30-Mar-2014 02:00:00 Into DST? true
26-Oct-2014 01:00:00 Into DST? false
29-Mar-2015 02:00:00 Into DST? true
25-Oct-2015 01:00:00 Into DST? false
...

With Java 8, you can get the same information using ZoneRules with its nextTransition and previousTransition methods.

Handle daylight savings time and representing UTC in Date object

You are currently mixing calls to two very different APIs (old and outdated java.util.Date and classes from java.time, like LocalDateTime). I would stick to the newer API because it makes life a lot easier if you want to express the same instant in two different time zones.

You can still use the LocalDateTime in order to parse the value from the String and then add a ZoneId to make it represent a real moment in time.

Here's an example:

public static void main(String[] args) {
// your example datetime String
String datetime = "20220313 02:02:00.000";
// a pattern representing the format of your datetime String
String formatPattern = "uuuuMMdd HH:mm:ss.SSS";
// a formatter using that pattern (can parse and format)
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(formatPattern);
// the two time zones involved
ZoneId americaNewYork = ZoneId.of("America/New_York");
ZoneId utc = ZoneId.of("UTC");
// the date and time of day without any zone or offset
LocalDateTime zonelessDateTime = LocalDateTime.parse(datetime, dtf);
// that date and time of day in New York
ZonedDateTime newYorkTime = zonelessDateTime.atZone(americaNewYork);
System.out.println(newYorkTime.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
// the same instant in UTC (same date, different time of day, no offset
ZonedDateTime utcTime = zonelessDateTime.atZone(utc);
System.out.println(utcTime.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
}

As you can see in the output, the hours of day are different and so is the zone:

2022-03-13T03:02:00-04:00[America/New_York]
2022-03-13T02:02:00Z[UTC]

If you have to produce/consume java.util.Dates, you can make use of compatibility methods that have been implemented for reasons like yours: Dealing with a considerable large amount of legacy code.

Short: A java.time.ZonedDateTime and a java.time.OffsetDateTime are representations of moments in time, instants. Fortunately, theres a java.time.Instant, too, and you can convert a java.util.Datefrom/to anInstant. There's Date.from(Instant)andDate.toInstant(). Here's how you would use the results of the code example above in order to have the values as Date`:

// convert the Instants represented by the ZonedDateTimes to Dates
Date newYorkDate = Date.from(newYorkTime.toInstant());
Date utcDate = Date.from(utcTime.toInstant());
// print the Date values
System.out.println(newYorkDate);
System.out.println(utcDate);

These lines would produce the following output:

Sun Mar 13 08:02:00 CET 2022
Sun Mar 13 03:02:00 CET 2022

Please have a closer look at the values of the java.util.Dates.

Zones implicitly changed and values adjusted (even though a Date does not really have a zone). You have basically no real control over zone shifts and time conversions.

There are several reasons for a totally new and different datetime API introduced in Java 8… The mentioned is just one of them.



Is there any way to represent "20220313 02:02:00.000" in java Date object?

Yes, there is… You could create the Date and return it. How this Date instance will be represented as String depends on the TimeZone used. See this:

// create the date
Date date = Date.from(
LocalDateTime.parse("20220313 02:02:00.000", dtf)
.atZone(utc)
.toInstant()
);
// get the milliseconds since 1970-01-01, the only numerical value stored by a Date
long epochMillis = date.getTime();
// create a format for visualization
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
// add a time zone to the format
isoFormat.setTimeZone(TimeZone.getTimeZone("America/New_York"));
// and use it to print the date in that zone
System.out.println(epochMillis + " in New York: " + isoFormat.format(date));
// set the time zone of the format to UTC
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
// and use it to print the date in a different zone
System.out.println(epochMillis + " in UTC: " + isoFormat.format(date));

The output is the following, mind that the same Date is used:

1647136920000 in New York: 2022-03-12T21:02:00.000
1647136920000 in UTC: 2022-03-13T02:02:00.000

OK, the format is not stored in the Date variable, but the underlying value is, at least, which makes it representable in different formats that have different time zones.

Thing to think about:

Do you think the time zone should be part of the format rather than part of a datetime object itself? The answer to this question could be mapped to the question Do you want to use java.util.Date or java.time? ;-)



Related Topics



Leave a reply



Submit