Time Zone Shift Processing and Daylight Saving Time Using Joda

I am trying to parse datetime strings and create Joda DateTime objects.

My data comes from an outdated database that stores time and time strings, without specifying a time zone / offset. Although the timeline / offset of the date and time strings is not saved, this is a business rule of the legacy system in which all data is stored in Eastern Time. Unfortunately, I do not have the authority to update the way the legacy DB stores datetime rows.

This way I parse the datetime strings using the JODA time zone "US / Eastern".

This approach throws an illInstance exception when the dateTime string falls within an hour, which "disappears" when summer saving is turned on.

I created the following sample code to demonstrate this behavior and show the proposed workaround.

public class FooBar {
public static final DateTimeZone EST = DateTimeZone.forID("EST");
public static final DateTimeZone EASTERN = DateTimeZone.forID("US/Eastern");

public static final DateTimeFormatter EST_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS").withZone(EST);
public static final DateTimeFormatter EASTERN_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS").withZone(EASTERN);


public static void main(String[] args) {
    final String[] listOfDateTimeStrings = {"2014-03-09 02:00:00.000", "2014-03-08 02:00:00.000"}; 

    System.out.println(" *********** 1st attempt  *********** ");
    for (String dateTimeString: listOfDateTimeStrings){
        try{
            final DateTime dateTime = DateTime.parse(dateTimeString, EASTERN_FORMATTER);
            System.out.println(dateTime);       
        }
        catch(Exception e){
            System.out.println(e.getMessage());
        }
    }

    System.out.println(" *********** 2nd attempt  *********** ");
    for (String dateTimeString: listOfDateTimeStrings){
        try{
            final DateTime dateTime = DateTime.parse(dateTimeString, EST_FORMATTER);
            System.out.println(dateTime);       
        }
        catch(Exception e){
            System.out.println(e.getMessage());
        }
    }

    System.out.println(" *********** 3rd attempt  *********** ");
    for (String dateTimeString: listOfDateTimeStrings){
        try{
            DateTime dateTime = DateTime.parse(dateTimeString, EST_FORMATTER);
            dateTime = dateTime.withZone(EASTERN);
            System.out.println(dateTime);       
        }
        catch(Exception e){
            System.out.println(e.getMessage());
        }
    }       

}

}

The output:

 *********** 1st attempt *********** 
Cannot parse "2014-03-09 02: 00: 00.000": Illegal instant due to time zone offset transition (America / New_York)
2014-03-08T02: 00: 00.000-05: 00
 *********** 2nd attempt *********** 
2014-03-09T02: 00: 00.000-05: 00
2014-03-08T02: 00: 00.000-05: 00
 *********** 3rd attempt *********** 
2014-03-09T03: 00: 00.000-04: 00
2014-03-08T02: 00: 00.000-05: 00

In the "third attempt" I get the expected result: the first datetime has an offset of -04: 00. since it falls into the first hour of DST for 2015. The second timestamp has an offset of -05: 00 because it is outside the DST.

Is it safe to do this:

DateTime dateTime = DateTime.parse(dateTimeString, A_FORMATTER_WITH_TIME_ZONE_A);
dateTime = dateTime.withZone(TIME_ZONE_B);

( ), , - - / .

: Joda?

+4
2

. withZone (...) :

- , .

, , EST "America/New_York" (, "US/Eastern" ) . (EST) ( DST), DST, . EST , ,

a) ( , EST ),

b) , EST ( ) DST.

/ ( EST America/New_York). , Joda-Time. JSR-310 , , (, java.util.Calendar -).

@Jim Garrison, , , ( ).

( - . ):

, EST, "/_York" . EST- New-York-time ( withZone(EASTERN). , , () ( DateTime, ). :

public static final DateTimeZone EST = DateTimeZone.forID("EST");
public static final DateTimeZone EASTERN = DateTimeZone.forID("US/Eastern");
public static final DateTimeFormatter EST_FORMATTER = 
  DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS").withZone(EST);

// in your parsing method...
String input = "2014-03-09 02:00:00.000";
DateTime dt = EST_FORMATTER.parseDateTime(input);
System.out.println(dt); // 2014-03-09T02:00:00.000-05:00
System.out.println(dt.withZone(EASTERN)); // 2014-03-09T03:00:00.000-04:00

OP:

, EST ( UTC-05, EASTERN ( "America/New_York" EST EDT) , , , . , :

, - , LocalDateTime.

= >

// Joda-Time cannot parse "EDT" so we use hard-coded offsets
public static final DateTimeZone EST = DateTimeZone.forOffsetHours(-5);
public static final DateTimeZone EDT = DateTimeZone.forOffsetHours(-4);

public static final DateTimeZone EASTERN = DateTimeZone.forID("America/New_York");
public static final org.joda.time.format.DateTimeFormatter FORMATTER = 
    org.joda.time.format.DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS");

= >

String input = "2014-03-09 02:00:00.000";
LocalDateTime ldt = FORMATTER.parseLocalDateTime(input); // always working
System.out.println(ldt); // 2014-03-09T02:00:00.000
DateTime result;

try {
    result = ldt.toDateTime(EASTERN);
} catch (IllegalInstantException ex) {
    result = ldt.plusHours(1).toDateTime(EDT); // simulates a PUSH-FORWARD-strategy at gap
    // result = ldt.toDateTime(EST); // the same instant but finally display with EST offset
}
System.out.println(result); // 2014-03-09T03:00:00.000-04:00
// if you had chosen <<<ldt.toDateTime(EST)>>> then: 2014-03-09T02:00:00.000-05:00

- OP:

toDateTime (DateTimeZone), DateTime, :

, , .

, ().

result = ldt.toDateTime(EASTERN).withEarlierOffsetAtOverlap();

, . : ( )

result = ldt.toDateTime(EDT).withEarlierOffsetAtOverlap();

EDT ( EST ) , . , withEarlierOffsetAtOverlap() . : ldt.plusHours(1) EDT . , , , , ldt.toDateTime(EST) , (EDT!= EST, plusHours(1) ). EDT, , JDK. , (EDT EST), (ldt.plusHours(1).toDateTime(EDT) result = ldt.toDateTime(EST)).

+3

, .

, , . , , . , , , , /.

/ , ( , ) , .

+3

Source: https://habr.com/ru/post/1622956/


All Articles