0

I have a date time that I am first converting to local time, followed by a conversion to another time zone. The first conversion works with no issue however the second conversion is ignored. What is the issue?

String input = "2020-05-20 01:10:05";
SimpleDateFormat localFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
localFormat.setTimeZone(TimeZone.getTimeZone(ZoneId.systemDefault()));

try {
    Date date = localFormat.parse(input);
    System.out.println(date); //Wed May 20 01:10:05 PDT 2020 <--- Logs this (Expected)

    SimpleDateFormat estFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    estFormat.setTimeZone(TimeZone.getTimeZone("America/New_York"));
    
    String newDate = estFormat.format(date);
    System.out.println(newDate); //2020-05-20 04:10:05 <--- Logs this (Expected)

    Date dateEst = estFormat.parse(newDate);
    System.out.println(dateEst); //Wed May 20 01:10:05 PDT 2020 <--- Logs this (Unexpected) Should be Wed May 20 04:10:05 EST 2020

}catch (Exception e){
    e.printStackTrace();
}

It seems like the second estFormat.parse() is ignored when trying to convert to America/New_York time zone.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
WHOATEMYNOODLES
  • 845
  • 9
  • 25
  • 2
    I recommend you don’t use `SimpleDateFormat`, `Date` and `TimeZone`. Those classes are poorly designed and long outdated, the first in particular notoriously troublesome. Instead use `LocalDateTime`, `ZoneId`, `ZonedDateTime` and `DateTimeFormatter`, all from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Aug 27 '21 at 19:48
  • 1
    And for any reason, if you have to stick to Java 6 or Java 7, you can use [ThreeTen-Backport](http://www.threeten.org/threetenbp/) 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](https://developer.android.com/studio/write/java8-support-table) and [How to use ThreeTenABP in Android Project](https://stackoverflow.com/questions/38922754/how-to-use-threetenabp-in-android-project) – Arvind Kumar Avinash Aug 27 '21 at 20:29

3 Answers3

3

java.time

I warmly recommend that you use java.time, the modern Java date and time API, for your date and time work. Once you get used to the slightly different mindset, you will likely also find the resulting code clearer and more natural to read. Let’s first define the constant stuff as constants:

private static final DateTimeFormatter FORMATTER
        = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ROOT);
private static final ZoneId FROM_ZONE = ZoneId.of("America/Los_Angeles");
private static final ZoneId TO_ZONE = ZoneId.of("America/New_York");

With these we can do our work:

    String input = "2020-05-20 01:10:05";
    
    ZonedDateTime fromDateTime
            = LocalDateTime.parse(input, FORMATTER).atZone(FROM_ZONE);
    System.out.println("From:      " + fromDateTime);
    
    ZonedDateTime toDateTime = fromDateTime.withZoneSameInstant(TO_ZONE);
    System.out.println("To:        " + toDateTime);
    
    String formatted = toDateTime.format(FORMATTER);
    System.out.println("Formatted: " + formatted);

Output is:

From:      2020-05-20T01:10:05-07:00[America/Los_Angeles]
To:        2020-05-20T04:10:05-04:00[America/New_York]
Formatted: 2020-05-20 04:10:05

Edit:

How would I get it to have EST 2020 at the end?

A good option for most purposes is to use a localized formatter:

private static final DateTimeFormatter TARGET_FORMATTER
        = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
                .withLocale(Locale.US);

Like this:

    String formatted = toDateTime.format(TARGET_FORMATTER);
Formatted: May 20, 2020 at 4:10:05 AM EDT

A detail, we didn’t get EST at the end because New York and most of the East coast of Northern America uses summer time (DST) and hence is on Eastern Daylight time, EDT, in May.

What went wrong?

It seems that you were expecting your Date object to carry the time zone of the formatter that parsed it, America/New_York. An old-fashioned Date object cannot do that. It’s just a dumb point in time without any time zone or other additional information. What confuses many is that its toString method uses the default time zone of the JVM to render the string returned, thus giving the false impression of a time zone being present. In contrast the modern ZonedDateTime, as the name says, does hold a time zone.

Link

Oracle tutorial: Date Time explaining how to use java.time.

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

First, don't use Date unless you're maintaining legacy code.

Second, SimpleDateFormat parsed the date correctly. You're not using estFormat to format the date as you did in the previous (correct) example. Try:

System.out.println(estFormat.format(dateEst));

This is a good overview of the different types of date-related entities in Java and is worthwhile reading. Here's an excerpt you may find useful:

The java.util.Date has no concept of time zone, and only represents the number of seconds passed since the Unix epoch time – 1970-01-01T00:00:00Z. But, if you print the Date object directly, the Date object will be always printed with the default system time zone.

Paul
  • 19,704
  • 14
  • 78
  • 96
0

I had noticed one thing the type of the first variable is String and the type of the Second variable is Date. So probably type conversion is creating a problem here. There is nothing like ignoring a second time.

harsh 1868
  • 56
  • 6