简体   繁体   中英

Facing DateFormat issue in Android, CDT converting into IST

The time I am getting from Android phone is

"Mon May 9 09:34:13 CDT 2016\\r\\r\\n" but after parsing the same date using date format SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy",Locale.US);

After parsing it gives me a date into the

"Mon May 09 20:04:56 IST 2016".

It clearly shows that the hours is increase by 11 hours.

How to address this issue, Could anybody help me?

Don't forget Date class is a class with no format at all....

if you want to print a date you need to use the format method of the intenace you created...

example:

public static void main(String[] args) throws ParseException {
    String myDate = "Mon May 9 09:34:13 CDT 2016";
    SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
    Date d = dateFormat.parse(myDate);
    System.out.println(d);  // this is not formatted printing Mon May 09 16:34:13 CEST 2016
    System.out.println(dateFormat.format(d)); // this is printed using the same format you use above
}

tl;dr

Your India time is correctly adjusted 10.5 hours ahead of Chicago time. Feature, not a bug. (I am assuming your :56 seconds was a typo in your Question.)

If you want no such adjustment, but instead want the same date and same time-of-day assigned to a different time zone, then do this:

ZonedDateTime.parse(
    "Mon May 9 09:34:13 CDT 2016" ,  // If at all possible, avoid using such an awful format for exchanging date-time strings. Always use standard ISO 8601 formats instead.
    DateTimeFormatter.ofPattern( "EEE MMM d HH:mm:ss z uuuu" )
)                                    // Returns a `ZonedDateTime` object.
.withZoneSameLocal( 
    ZoneId.of( "Asia/Kolkata" ) 
)                                    // Returns a fresh `ZonedDateTime` object, with values based on the original but for the change in assigned zone.
.toString()                          // Generates a String is standard ISO 8601 format, extending the standard by appending the name of the time zone in square brackets.

2016-05-09T09:34:13+05:30[Asia/Kolkata]

We get the same date and same time-of-day, but a different offset-from-UTC means this is a different moment, a different point on the timeline.

Correct values

[Note: I am assuming the :56 in your Mon May 09 20:04:56 IST 2016 was a typo, and should have been :13 . ]

The strings Mon May 9 09:34:13 CDT 2016 and Mon May 09 20:04:13 IST 2016 represent the same moment. This is a feature, not a bug. If by CDT you mean a time zone such as America/Chicago , that value on that date represents a moment five hours behind UTC, -05:00 . If by IST , you mean a time zone such as Asia/Kolkata , India on that date is five and a half hours ahead of UTC, +05:30 . Add those offsets together, and we get a difference of ten and a half hours. This fits: 09:34:13 plus 10.5 hours is 20:04:13 .

In other words, if someone in Chicago is talking to someone in Kolkata on the telephone, if they both look up at the time on the clock on their own wall, one will see 09:34:13 while the other sees 20:04:13.

Perhaps you wanted to purposely not adjust for time zone, but re-create the same date with the same time-of-day but in a different time zone. This would not be the same moment, this would a different point on the timeline. See below for such code.

java.time

You are using troublesome old classes that were supplanted long ago by the modern java.time classes.

When possible, avoid manipulating strings as a way of handling date-time. Instead, use smart objects, not dumb strings.

Instant instant = Instant.now() ;  // Capture current moment in UTC.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ; 
ZonedDateTime zdt = instant.atZone( z ) ;  // Same moment, same point on the timeline, but different wall-clock time.

If you must exchange date-time values as text, use standard ISO 8601 formats rather than formats such as seen in your Question.

Also, never use the 3-4 letter pseudo-time-zones such as CDT or IST . These are not true time zones, are not standardized, and many are not unique(!). Use full time zone names is the IANA-specified Continent/Region format.

But to your Question directly, parsing the string Mon May 9 09:34:13 CDT 2016 . Define a formatting pattern to match.

String input = "Mon May 9 09:34:13 CDT 2016";

DateTimeFormatter f = DateTimeFormatter.ofPattern( "EEE MMM d HH:mm:ss z uuuu" );
ZonedDateTime zdt = ZonedDateTime.parse( input , f );

zdt.toString(): 2016-05-09T09:34:13-05:00[America/Chicago]

ZonedDateTime::withZoneSameInstant

Adjust into India time.

ZoneId zKolkata = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdtKolkata = zdt.withZoneSameInstant( zKolkata );

zdtKolkata.toString(): 2016-05-09T20:04:13+05:30[Asia/Kolkata]

Same behavior as you saw with the legacy classes. Adding 10.5 hours to 09:34:13 gets us 20:04:13. Same moment, same point on the timeline, but different wall-clock time.

ZonedDateTime::withZoneSameLocal

But what if you want the same date and same time-of-day, but switch out the time zone? This would result in a different moment, different points on the timeline (assuming the two zones don't share the same offset). The ZonedDateTime does support this manipulation via the ZonedDateTime::withZoneSameLocal​(ZoneId zone) method.

ZonedDateTime zdtSameLocalKolkata = zdt.withZoneSameLocal( zKolkata );

zdtSameLocalKolkata.toString(): 2016-05-09T09:34:13+05:30[Asia/Kolkata]

Now we see the time-of-day unchanged, still 09:34:13. But the offset-from-UTC is different than Chicago, so we know this does not represent the same moment.

You can verify the fact they are different moments by adjusting both into UTC. The easy way to make that adjustment is to extract Instant object. An Instant is always in UTC by definition.

Instant instantOfZdtChicago = zdt.toInstant() ;
Instant instantOfZdtSameLocalKolkata = zdtSameLocalKolkata.toInstant():

instantOfZdtChicago.toString(): 2016-05-09T14:34:13Z

instantOfZdtSameLocalKolkata.toString(): 2016-05-09T04:04:13Z


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat .

The Joda-Time project, now in maintenance mode , advises migration to the java.time classes.

To learn more, see the Oracle Tutorial . And search Stack Overflow for many examples and explanations. Specification is JSR 310 .

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM