Unparseable Date error thrown when converting date to SimpleDateFormat - java

I am trying to convert a UTC string to just the hours and the minutes. I get the UTC string from an API but have given an example below of what it looks like.
When it gets to someDate it throws an Unparseable Date error and references the string setString.
Can anyone see what I am doing wrong here?
Example of how I am getting the date from UTC
String utcStr = "1521698232";
Date setSunrise = new Date(Long.parseLong(sunrise)*1000);
Trying to convert it to HH:mm
String setString = "Thu Mar 22 05:57:06 GMT+00:00 2018";
Date someDate = new SimpleDateFormat("EEE MMM d HH:mm:ss z'+00:00' yyyy").parse(setString);
Date printDate = new SimpleDateFormat("hh:mm").format(someDate);

tl;dr
You are working too hard, going in a roundabout manner. Also, you are using troublesome old obsolete classes. Also, I suspect you are ignoring the crucial issue of time zone.
Here is a much simpler and cleaner modern solution, with consideration for time zone.
Instant.ofEpochSecond( // Represent a moment in time in UTC, with a resolution of nanoseconds.
Long.parseLong( "1521698232" ) // Count of whole seconds since epoch of 1970-01-01T00:00:Z.
) // Returns a `Instant` object.
.atZone( // Apply a time zone (`ZoneId`) to adjust from UTC to the wall-clock time of the target audience.
ZoneId.of( "Asia/Kolkata" ) // Use only proper time zone names `continent/region`. Never use 3-4 letter codes such as `IST` or `EST`.
) // Produces a `ZonedDateTime` object.
.toLocalTime() // Extract only the time-of-day as a `LocalTime` object.
.truncatedTo( ChronoUnit.MINUTES ) // Lop off any seconds and fractional second.
.toString() // Generate a String in standard ISO 8601 format: HH:MM:SS.SSSSSSSSS
11:27
Count-from-epoch
convert a UTC string
No such thing as a “UTC string”.
Your input seems to represent a number of whole seconds since the epoch reference of first moment of 1970 UTC, 1970-01-01T00:00Z. This is sometimes referred to as Unix Time or POSIX Time.
ISO 8601
"Thu Mar 22 05:57:06 GMT+00:00 2018";
This is a terrible format for a date-time value.
Instead use standard ISO 8601 strings when exchanging date-time values as text. The java.time classes use ISO 8601 formats by default when parsing/generating strings.
Avoid legacy date-time classes
The Date and SimpleDateFormat classes are part of the troublesome old date-time classes that are now legacy, supplanted by the java.time classes.
Date is replaced by Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
String input = "1521698232" ; // Count of seconds since epoch reference of 1970-01-01T00:00Z.
long secondsSinceEpoch = Long.parseLong( input ) ;
Instant instant = Instant.ofEpochSecond( secondsSinceEpoch ) ;
instant.toString(): 2018-03-22T05:57:12Z
As discussed above, the Instant (like Date) is in UTC. If you ask for the time-of-day, you'll get a time-of-day in UTC. More likely you really want the time-of-day for that moment by the wall-clock time used by people in a certain region (a time zone).
A time zone is crucial in determining a date and time-of-day. For any given moment, the date and time-of-day varies around the globe by zone.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter pseudo-zones such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
Apply that zone to adjust from UTC, producing a ZonedDateTime object.
ZonedDateTime zdt = instant.atZone( z ) ;
zdt.toString(): 2018-03-22T18:57:12+13:00[Pacific/Auckland]
Now ask for the time-of-day. The resulting LocalTime objects lacks a date and lacks a time zone. It is just a time-of-day on a 24-hour clock.
LocalTime lt = zdt.toLocalTime() ;
If you only care about the hours and minutes, lop off and seconds and fractional second by truncating. Specify the level of truncation via the ChronoUnit class.
LocalTime ltTrunc = lt.truncatedTo( ChronoUnit.MINUTES ) ;
Generate a String in standard ISO 8601 format.
String output = ltTrunc.toString() ; // Generate a `String` in standard ISO 8601 format.
18:57
To generate a String in other formats, search Stack Overflow for DateTimeFormatter. You will find many discussions and examples.
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?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

The +00:00 part is a UTC offset, and you can't treat as a literal (inside quotes, like you did). That's an important information, because it tells you how many hours ahead or behind UTC the date refers to (in this case, it's zero, so it's the same as UTC itself).
Another detail is that the day-of-week and month name are in English, so you should set a java.util.Locale in your class. If you don't use a locale, it'll use the JVM default and there's no guarantee that it'll always be English in all environments. If you're sure about the language used in the inputs, set the locale:
String setString = "Thu Mar 22 05:57:06 GMT+00:00 2018";
SimpleDateFormat parser = new SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy", Locale.ENGLISH);
Date someDate = parser.parse(setString);
For the output, 2 things:
using hh will print the hour-of-am-pm, which means values from 1 to 12. If you want the hours value from 0 to 23, use HH - this is all explained in the docs
the value of the hours will be converted to the device's default timezone, which means that not always will be the same of the input (in my case, my country is using -03:00 - 3 hours behind UTC - so the value of the hours is 2 AM.
To use the same offset in the input, you must set it in the formatter:
SimpleDateFormat formatter = new SimpleDateFormat("HH:mm");
formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
String printDate = formatter.format(someDate); // 05:57
To use java-time classes, the other answer by Basil tells you how to use this API in Android. I'd just like to add the similar code to parse your specific input:
String setString = "Thu Mar 22 05:57:06 GMT+00:00 2018";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("EEE MMM d HH:mm:ss O yyyy", Locale.ENGLISH);
OffsetDateTime odt = OffsetDateTime.parse(setString, parser);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");
String printDate = formatter.format(odt);

Related

Java convert millisecond timestamp to date with respect to given timezone

I have seen many resources on this but one thing I cant get is when converting the millisecond timestamp, how I add a corresponding time zone, during the conversion process.
Date date = new Date(Long.valueOf(dateInMil*1000L);
SimpleDateFormat myDate = new SimpleDateFormat("EEE, MMM d, ''yy");
String formatted = myDate.format(date);
Now if I have a time zone/offset in string formate i.e. "-04:00" or "+2:00" how to apply it to the above so I can get the proper date ?
tl;dr
Instant.ofEpochMilli( myCountOfMilliseconds )
.atZone( ZoneId.of( "Africa/Tunis" ) )
.toString()
java.time
The modern approach uses the java.time classes rather than the troublesome old Calendar/Date classes that are now legacy.
Assuming your count of milliseconds is a count since the epoch reference of first moment of 1970 in UTC (1970-01-01T00:00), then parse as a Instant.
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = Instant.ofEpochMilli( myCountOfMilliseconds ) ;
To move from UTC to another time zone, apply a ZoneId to get a ZonedDateTime.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Objects vs text
After assigning the time zone, then generate a string in your desired format (not before). You may be conflating date-time values (objects) with strings representing their value textually. Learn to think of smart objects, not dumb strings.
DateTimeFormatter
To generate a String in a particular format, use a DateTimeFormatter. Search Stack Overflow as this been covered many many times, as have the other concepts shown here. Of special note are the DateTimeFormatter.ofLocalized… methods.
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.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
I was doing a similar thing in my previous project.You can use setTimeZone method of SimpleDateFormat class. Something like this :
mydate.setTimeZone(TimeZone.getTimeZone("GMT -0400"));
DateTimeFormatter myDateFormatter
= DateTimeFormatter.ofPattern("EEE, MMM d, ''yy", Locale.ENGLISH);
long dateInSec = 1_554_321_098L;
String utcOffsetString = "-04:00";
ZoneOffset offset = ZoneOffset.of(utcOffsetString);
String date = Instant.ofEpochSecond(dateInSec)
.atOffset(offset)
.format(myDateFormatter);
System.out.println(date);
This prints
Wed, Apr 3, '19
The other example offset you gave, +2:00, is slightly more difficult since ZoneOffset.of requires either only hours (+2) or two-digit hours before the colon (+02:00). One solution is to fix the string before handing it to ZoneOffset:
String utcOffsetString = "+2:00";
utcOffsetString = utcOffsetString.replaceFirst("([-+])(\\d:\\d{2})", "$10$2");
ZoneOffset offset = ZoneOffset.of(utcOffsetString);
The result is still Wed, Apr 3, '19. If there were already 2-digit hours in the string, replaceFirst won’t replace anything, so you just get the same string back.
If I change the offset to +08:00, I get Thu, Apr 4, '19 instead.
Edit: I frankly find the regular expression I use for fixing the offset string quite unreadable. Here’s a simpler way of fixing it:
DateTimeFormatter offsetFormatter = DateTimeFormatter.ofPattern("O", Locale.ENGLISH);
ZoneOffset offset = ZoneOffset.from(offsetFormatter.parse("GMT" + utcOffsetString));
Like Basil Bourque I am using java.time. See all the details in his answer.
Not exactly what your looking for but close
String timeZone = "America/Los_Angeles"
TimeZone tz = TimeZone.getTimeZone(timeZone);
SimpleDateFormat sdf = new SimpleDateFormat("EEEEE MMMMM d hh:mm a");
sdf.setTimeZone(tz);
Date localizedTime = sdf.format(new Date());
If you keep the localization strings instead of the offsets this will work. Or you can make a map.

Convert UTC time to local time zone

I have to convert UTC time into user local time zone. Currently, I have the two parameters one is time in long format and another is time zone name in string format like "(UTC-05:00) Eastern Time (US and Canada), (UTC-06:00) Central Time (US and Canada)" etc.
So now using these two parameters I have to get date time in string format. I am facing the issue while I am trying to convert the date into a string because the SimpleDateFormat.format(...) will convert the date using its default time zone.
Below are the code portion
public static void main(String[] args)
{
long time = 1490112300000L;
System.out.println("UTC Time "+ convertLongToStringUTC(time));
String EST = "(UTC-05:00) Eastern Time (US and Canada)";
TimeZone timeZone1 = TimeZone.getTimeZone(EST);
System.out.println("EST "+ convertTimeZone(time, timeZone1));
String CST = "(UTC-06:00) Central Time (US and Canada)";
TimeZone timeZone2 = TimeZone.getTimeZone(CST);
System.out.println("CST "+ convertTimeZone(time, timeZone2));
String IST = "IST";
TimeZone timeZone = TimeZone.getTimeZone(IST);
System.out.println("IST "+ convertTimeZone(time, timeZone));
}
public String convertTimeZone(long time, TimeZone timeZone)
{
Date date = new Date(time);
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
format.setTimeZone(timeZone);
return format.format(date);
}
public String convertLongToStringUTC(long time)
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String utcTime = sdf.format(new Date(time));
return utcTime;
}
Also let me know if we can achieve this using offset ?
Use this constructor
SimpleDateFormat(String pattern, Locale locale)
Constructs a SimpleDateFormat using the given pattern and the default
date format symbols for the given locale. Note: This constructor may
not support all locales. For full coverage, use the factory methods in
the DateFormat class.
Java Doc
tl;dr
Instant.ofEpochMilli( 1_490_112_300_000L )
.atOffset( ZoneOffset.of( "-05:00" ) )
Instant.ofEpochMilli( 1_490_112_300_000L )
.atZone( ZoneId.of( "America/New_York" ) )
Details
The Answer by Dennis is close. I will provide further information.
Your Question is not exactly clear about the inputs. I will assume your long integer number represents a moment in UTC.
An offset-from-UTC is an number of hours and minutes and seconds before or after UTC. In java.time, we represent that with a ZoneOffset.
While ZoneId technically works (as seen in code by Dennis), that is misleading as a zone is much more than an offset. A zone is a region’s history of various offsets that were in effect at different periods of history. A zone also includes any planned future changes such as DST cutovers coming in the next months.
ZoneOffset offset = ZoneOffset.of( 5 , 30 ); // Five-and-a-half hours ahead of UTC.
ZoneOffset offset = ZoneOffset.of( "+05:30" );
Tip: Always include the padding zero on the hours. While not always required in various protocols such as ISO 8601, I have seen software systems burp when encountering single-digit hours like +5:00.
If you know the intended time zone for certain, use it. A zone is always better than a mere offset as it brings all that historical information of other offsets for the past, present, and future.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Asia/Kolkata" );
I am guessing your number is a number of milliseconds since the epoch of 1970-01-01T00:00:00Z.
Instant instant = Instant.ofEpochMilli( 1_490_112_300_000L );
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
You can adjust into a time zone.
ZonedDateTime zdt = instant.atZone( z );
These issues have been covered many times in Stack Overflow. Hence the down-votes you are collecting (I am guessing). Please search Stack Overflow thoroughly before posting.
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.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Using Java 8 you can do
OffsetDateTime dt = Instant.ofEpochMilli(System.currentTimeMillis())
.atOffset( ZoneOffset.of("-05:00"));
//In zone id you put the string of the offset you want

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?
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?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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
}

DateFormat format method doesn't display a parsed date to a particular TimeZone

I converted a date string to Date by SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(DateinString).
Here instead of converting to UTC it is converting to my Local TimeZone. I checked it by displaying this parsed date through format method of DateFormat.
So I have to re format it back to UTC.Now when I am trying to display this parsed date to UTC TimeZone through the same format method, it is still displaying in local TimeZone. Following is my code to format the parsed date to UTC-
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
cal.setTime(alreadyParsedDateTime); //
System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(cal.getTime()));
My sample date string is "2015-12-23T15:00:00-0800"
After parse -- alreadyParsedDateTime.toString():: Thu Dec 24 04:30:00 IST 2015
After parse --
System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(alreadyParsedDateTime)):: 2015-12-24T04:30:00
After the above mentioned re format of the parsed date to UTC --
System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(cal.getTime())):: 2015-12-24T04:30:00
Expected date format is:: 2015-12-23T23:00:00
I don't know why the format method not working in an expected way or there is any trick to do the same. Kindly help..
There are two different topics here; parsing and formatting.
1. Parsing
SimpleDateFormat.parse() will try to parse the timezone from the supplied date string. If the date string you are parsing does not include an explicit timezone, then the "default" timezone on the SimpleDateFormat object will be used. You can set the default time zone with the setTimeZone() method. Please see the API docs for SimpleDateFormat.parse() and DateFormat.setTimeZone() for reference.
Here is an example that shows how the parsing is influenced by the timezone set with setTimeZone():
String dateString = "2015.12.10 13:58:18";
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
sdf1.setTimeZone(TimeZone.getTimeZone("GMT"));
Date date1 = sdf1.parse(dateString);
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
sdf2.setTimeZone(TimeZone.getTimeZone("EST"));
Date date2 = sdf2.parse(dateString);
// Shows that the parsing honours time zone -- will print:
// Thu Dec 10 14:58:18 CET 2015 (original date was parsed as GMT)
// Thu Dec 10 19:58:18 CET 2015 (original date was parsed as EST)
System.out.println(date1);
System.out.println(date2);
2. Formatting
Assuming that the date has been parsed correctly, then your problem is with the formatting. You need to set the timezone for the actual SimpleDateFormat object that you are using for formatting. I modified your code to do this and it will now print what you expet:
Calendar cal = Calendar.getInstance();
cal.setTime(alreadyParsedDateTime);
SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
sdf3.setTimeZone(TimeZone.getTimeZone("UTC"));
// Prints: 2015-12-23T23:00:00 for your example date string
System.out.println(sdf3.format(cal.getTime()));
tl;dr
Current moment in UTC.
Instant.now() // Capture current moment in UTC.
.toString() // Generate string in standard ISO 8601 format.
2018-02-11T22:13:28.650328Z
Adjust into another time zone.
instant.atZone( // Apply a `ZoneId` to `Instant` object to get a `ZonedDateTime` object.
ZoneId.of( "Pacific/Auckland" )
).toString()
2018-02-12T11:13:28.650328+13:00[Pacific/Auckland]
Or capture current moment directly into that zone.
ZonedDateTime.now( // Capture current moment as seen on the wall-clock time of the people in a particular region.
ZoneId.of( "Pacific/Auckland" )
).toString() // Generate string in standard ISO 8601 format, wisely extended by appending the name of the time zone in square brackets.
2018-02-12T11:13:28.650328+13:00[Pacific/Auckland]
Details
The Answer by Grodriguez is correct but outdated.
java.time
The modern approach uses the java.time classes that supplant the troublesome old legacy date-time classes.
Your input string complies with the ISO 8601 formatting standard. The java.time classes use these formats by default when parsing/generating strings. So no need to specify a formatting pattern.
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Capture the current moment in UTC.
Instant instant = Instant.now() ; // Current moment in UTC.
To view that same simultaneous moment through the lens of a wall-clock time used by the people of another region (time zone), apply a ZoneId to get a ZonedDateTime object.
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Note that we are working with smart objects here, not dumb strings. Do not conflate the date-time objects with mere strings that may represent their values textually.
If you want to generate a String in standard ISO 8601 format, call the toString method.
String outputA = instant.toString() ;
String outputB = zdt.toString() ;
To generate strings in other formats, use the DateTimeFormatter or DateTimeFormatterBuilder classes. Both are covered extensively on Stack Overflow, so search for more info.
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.
With a JDBC driver complying with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings or java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

SimpleDateFormat specify timeZone [duplicate]

I am working on a project that fetches Date/Time from backend in IST(Indian standard Time) as shown "2013-01-09T19:32:49.103+05:30". However when i parse it using following DateFormat
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
followed by parsing..
Date date = sdf.parse("2013-01-09T19:32:49.103+05:30");
System.out.println("XYZ ==============>"+date);
its Displaying date in GMT format as output i.e
Wed Jan 09 14:02:49 GMT+00:00 2013.
I have tried it using TimeZone class as..
TimeZone timeZone=TimeZone.getTimeZone("IST");
sdf.setTimeZone(timeZone);
but no effect..
How could i get a Date class Object having Date in IST format instead of GMT...
Please provide an appropriate solution..
EDIT:
This is how Code Looks Like:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
TimeZone timeZone=TimeZone.getTimeZone("IST");
sdf.setTimeZone(timeZone);
Date date = sdf.parse("2013-01-09T19:32:49.103+05:30");
String formattedDate=sdf.format(date);
System.out.println("XYZ ==============>"+formattedDate);
Date does not have any time zone. It is just a holder of the number of milliseconds since January 1, 1970, 00:00:00 GMT. Take the same DateFormat that you used for parsing, set IST timezone and format your date as in the following example
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
Date date = sdf.parse("2013-01-09T19:32:49.103+05:30");
sdf.setTimeZone(TimeZone.getTimeZone("IST"));
System.out.println(sdf.format(date));
output
2013-01-09T19:32:49.103+05:30
Note that XXX pattern is used for ISO 8601 time zone (-08:00) since 1.7. If you are in 1.6 try Z. See SimpleDateFormat API for details of format patterns
How could i get a Date class Object having Date in IST format instead of GMT...
You can't. Date doesn't have a format or a time zone. It simply represents a number of milliseconds since the Unix epoch of midnight on January 1st 1970 UTC. Instead, Date.toString() always uses the default time zone.
To use a specific format and time zone, use DateFormat instead of Date.toString(). You can set the time zone with DateFormat.setTimeZone() and then convert a Date to a String using DateFormat.format(). DateFormat itself has some factory methods for creation, or you can use SimpleDateFormat if you want to specify a particular pattern.
As Abu says, Joda Time is a much better date/time API than the built-in one, although for just formatting a date/time the standard library doesn't do a bad job. Just note that DateFormat and its subclasses are generally not thread-safe.
tl;dr
OffsetDateTime.parse( "2013-01-09T19:32:49.103+05:30" ) // Parsed.
.toInstant() // Adjusted to UTC.
See live code in IdeOne.com.
ISO 8601
Your input string of 2013-01-09T19:32:49.103+05:30 happen to be in standard ISO 8601 format. The +05:30 at the end indicates an offset-from-UTC of five and a half hours ahead, used in India.
java.time
You are using troublesome old date-time classes, now legacy, supplanted by the java.time classes.
The java.time classes happen to use ISO 8601 formats by default when parsing/generating Strings representing date-time values. So no need to specify a formatting pattern at all.
As your input represents a moment on the timeline with an offset-from-UTC, we parse as a OffsetDateTime object.
OffsetDateTime odt = OffsetDateTime.parse( "2013-01-09T19:32:49.103+05:30" );
odt.toString(): 2013-01-09T19:32:49.103+05:30
To obtain a simple object in UTC value, extract an Instant. This Instant class is a basic building-block class of java.time. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
You can think of OffsetDateTime as an Instant plus a ZoneOffset.
Instant instant = odt.toInstant(); // UTC.
When calling toString, a String object is generated in standard ISO 8601 format. The Z on the end is short for Zulu and means UTC.
instant.toString(): 2013-01-09T14:02:49.103Z
An Instant is limited in various ways such as when generating Strings in various formats. So you may want to work with an OffsetDateTime adjusted into UTC as its offset; an offset-of-zero, in other words. The ZoneOffset class holds a constant for UTC, ZoneOffset.UTC.
OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC );
You can also apply an offset (or time zone) to an Instant. Call atOffset or atZone.
The Instant class is the basic building-block class of java.time. Likely to be used often in your code as best practice is to do most of your work in UTC.
OffsetDateTime odt = instant.atOffset( ZoneOffset.ofHoursMinutes( 5 , 30 ) );
Time zone
Note that an offset-from-UTC is not a time zone. A time zone is an offset plus a set of rules, past and present, for handling anomalies such as Daylight Saving Time (DST). So a time zone is always preferable to a mere offset if you are indeed sure of the correct zone.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
If you know the intended time zone, apply a ZoneId to get a ZonedDateTime object. But never assume without verifying with the source of your input data. Many different zones may share a particular offset. For example, in the case of our input here, the offset +05:30 happens to be used today in both India (Asia/Kolkata) and Sri Lanka (Asia/Colombo). Those two time zones may have different rules for different anomalies in their past, present, or future.
ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );
The toString method of ZonedDateTime extends standard ISO 8601 format in a wise way by appending the name of the time zone is square brackets. In this case, [Asia/Kolkata].
zdt.toString(): 2013-01-09T19:32:49.103+05:30[Asia/Kolkata]
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 java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
You can do this simply by use of Calender class. Please check below snippets:
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
calendar.setTimeInMillis(<--time stamp-->);
//calendar.setTime(<--date object of gmt date-->);
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd, yyyy 'at' hh:mm a");
sdf.setTimeZone(TimeZone.getDefault());
String result=sdf.format(calendar.getTime());

Categories