DateFomat give unparsable date error? - java

if I have a string date:
2013-11-14T00:00:00.000
What date format can I use to create a date with the offset?
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS Z");
dateFormat.setTimeZone(TimeZone.getDefault());
Date date = dateFormat.parse(myDate);
The above gives an unparsable date error.

"yyyy-MM-dd'T'HH:mm:ss.SSS"
Use SSS for milliseconds and remove Z as the date string does not have a time zone.
If you intend to print/log the date in another format (with a custom time zone, for example), you will have to use another instance of DateFormat:
"yyyy-MM-dd'T'HH:mm:ss.SSS" // to parse the date string
"yyyy-MM-dd'T'HH:mm:ss.SSSZ" // to format the date object

The .000 on the end is not a time zone designation; it looks like milliseconds. Try replacing the Z time zone designation with SSS for milliseconds.
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");

your supplied 2013-11-14T00:00:00.000 is not specified with the above pattern: "yyyy-MM-dd'T'HH:mm:ss.SSS Z" as sample valid input for this pattern would be:
2013-11-14T00:00:00.000 -0700
Either drop the Z or pass a string as the mentioned sample.

FYI, here is that same kind of code using Joda-Time 2.3.
Joda-Time uses that kind of ISO 8601 format as its default. No need for a formatter to parse that string. Merely pass the string to a DateTime constructor. The constructor automatically invokes a built-in ISO formatter.
String input = "2013-11-14T00:00:00.000";
// Specify a time zone rather than rely on default.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime dateTime = new DateTime( input, timeZone );
System.out.println( "dateTime: " + dateTime );
When run…
dateTime: 2013-11-14T00:00:00.000+01:00
If you need a java.util.Date for use with other classes, convert from Joda-Time.
java.util.Date date = dateTime.toDate();

Related

Convert YYYY-MM-DDThh:mm:ssTZD format date string to local time

In my spring boot application I have to convert ISO 8601 datetime to localdatetime without using JODA. Currently what I am doing is
String receivedDateTime = "2019-11-13T00:11:08+05:00";
ZonedDateTime zonedDateTime = ZonedDateTime.parse(receivedDateTime);
DateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
utcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = new Date();
try {
date = utcFormat.parse(zonedDateTime.toString());
} catch (ParseException e) {
e.printStackTrace();
}
When I am using receivedDateTime with +00:00 like "2019-11-13T00:11:08+00:00" then it does not give any parsing error but not converting either. When I use +01:00 at the end then it also gives the parsing error.
UPDATE: 1
As per #Deadpool answer, I am using it like
String receivedDateTime = "2019-11-13T00:11:08+05:00";
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd()
.optionalStart().appendOffset("+HHMM", "0000").optionalEnd()
.toFormatter();
OffsetDateTime dt = OffsetDateTime.parse(receivedDateTime, formatter);
LocalDateTime ldt = dt.toLocalDateTime();
System.out.println(ldt);
and the the value of ldt it print is 2019-11-13T00:11:08.
UPDATE 2:
I tried using C# the same example and it gives me this date time {2019-11-12 11:11:08 AM}, which looks correct as the input time GMT +5 Hours and local time is EST America. So, when it converted it then it went back to 12th of Nov. Here is the code
var timeString = "2019-11-13T00:11:08+05:00";
DateTime d2 = DateTime.Parse(timeString, null, System.Globalization.DateTimeStyles.RoundtripKind);
Console.WriteLine("Hello World!" + d2);
UPDATE 3: So it boils down to following solution input String "2019-11-13T06:01:41+00:00" and output is local date "2019-11-13T00:01:41" Where system defauld ZoneId is "America/Chicago" which is -06:00 GMT
private LocalDateTime convertUtcStringToLocalDateTime(String UtcDateTime) {
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd()
.optionalStart().appendOffset("+HHMM", "0000").optionalEnd()
.toFormatter();
OffsetDateTime dateTime = OffsetDateTime.parse(UtcDateTime, formatter);
return dateTime.atZoneSameInstant(ZoneId.of(ZoneId.systemDefault().getId())).toLocalDateTime();
}
Using java.time alone this is simpler than you seem to think:
String receivedDateTime = "2019-11-13T00:11:08+05:00";
OffsetDateTime parsedDateTime = OffsetDateTime.parse(receivedDateTime);
ZonedDateTime dateTimeInMyTimeZone
= parsedDateTime.atZoneSameInstant(ZoneId.systemDefault());
System.out.println(dateTimeInMyTimeZone);
When I ran this in America/Toronto time zone, the output was:
2019-11-12T14:11:08-05:00[America/Toronto]
Since your string contains an offset, +05:00, and no time zone, like Asia/Karachi, use an OffsetDateTime for parsing it. Then convert to your local time zone using the atZoneSameInstant method. Even though you asked for your local time, don’t be fooled into using LocalDateTime. That class represent a date and time without any time zone, which is not what you need (and seldom needed at all).
Fortunately it’s easy to avoid the old classes SimpleDateFormat, DateFormat, TimeZone and Date. They were always poorly designed, the first two in particular are notoriously troublesome. They are all long outdated now. Instead get all the functionality we dream of from java.time, the modern Java date and time API.
What happened in your code?
Don’t use 'Z' in a format pattern string (and I repeat, don’t use SimpleDateFormat).
No matter if you use ZonedDateTime or OffsetDateTime, when you use toString with offset zero (as parsed from +00:00), the offset is printed as Z, which matches the 'Z' in your format pattern string, so your second parsing works. Only parsing once, converting back to string and parsing again is needlessly complicated. Worse when the original offset was +01:00 or +05:00. These are rendered the same again from toString, so don’t match 'Z', which caused your ParseException. Never use 'Z' in a format pattern string. Z denotes an offset of zero and needs to be parsed as an offset for you to get the correct result.
By using DateTimeFormatter you can customize the date format with different offset format by making them optional
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd()
.optionalStart().appendOffset("+HHMM", "0000").optionalEnd()
.toFormatter();
And the use the OffsetDateTime to parse string representing with offset
A date-time with an offset from UTC/Greenwich in the ISO-8601 calendar system, such as 2007-12-03T10:15:30+01:00.
OffsetDateTime dateTime = OffsetDateTime.parse("2019-11-13T00:11:08+0000", formatter);
OffsetDateTime dateTime = OffsetDateTime.parse("2019-11-13T00:11:08+05:00", formatter);
If you want to convert it into local time zone time LocalDateTime then use atZoneWithSameInstant()
LocalDateTime local = dateTime.atZoneSameInstant(ZoneId.of("America/New_York")).toLocalDateTime()
Note : Don't use SimpleDateFormat and util.Date which are legacy old framework

Joda DateTime automatically change timezone when parsing string

I have string of a date in "iso8601" format and when I parse it using Joda "DateTime", the time zone of date changes automatically.
DateTime dateTime = new DateTime( "2017-05-22T08:10:00.000+0300" ) ;
System.out.println(dateTime);
and its output is:
2017-05-22T09:40:00.000+04:30
As you see time zone of first string is +3:00 and the time zone after parsing is +04:30. How can I parse first string without changing time zone? (so the time zone remains +03:00 even after parsing)
This constructor use default timezone of user. You need to set timezone manually with DateTime(Object object, DateTimeZone zone) construnctor.
Or, parse this string with usage of withOffsetParsed() like this:
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'hh:mm:ss.SSSZ");
DateTime dateTime = formatter.withOffsetParsed().parseDateTime("2017-05-22T08:10:00.000+0300");
You have to setup time zone manually something like this:
String str = "2017-05-22T08:10:00.000+0300" ;
DateTime dateTime = new DateTime() ;
System.out.println(dateTime);
String tzName = str.substring(text.length() - 5);
DateTimeZone tz = DateTimeZoneDateTimeZone forID(str.substring(3) + ":" + str.substring(text.length() - 2))
System.out.println(dateTime.withZone(tz));
You can use the inbuilt functionalities of JDK 8 date-time API to solve this easily. The following code prints 2017-05-22T08:10+03:00.
DateTimeFormatter df = DateTimeFormatter.ISO_OFFSET_DATE_TIME ;
OffsetDateTime date1 = OffsetDateTime.parse("2017-05-22T08:10:00.000+03:00", df);
System.out.println(date1); //prints 2017-05-22T08:10+03:00

Get only TimeZone field from new Date() in java

Requirement : I want to get only TimeZone field from new Date(), As of now from new Date() ,I am getting result as
Wed Jul 23 19:37:20 GMT+05:30 2014,But I want only GMT+05:30,Is there any way to get only this?
PS:I dont want to use split for getting timezone field.because this is my final option for achieving above requirement.
You should use the Calendar class and likely, the implementation GregorianCalendar. A lot of the Date functions have been deprecated in favor of using Calendar. Java 8 has the Clock API, but I'll assume Java 7 here.
That way you can do this:
Calendar calendar = new GregorianCalendar();
TimeZone tz = calendar.getTimeZone();
And work from there.
Assuming you have to work with a String input you can do something like this:
// format : dow mon dd hh:mm:ss zzz yyyy
String date = "Wed Jul 23 19:37:20 GMT+05:30 2014";
Pattern pattern = Pattern
.compile("^\\w{3}\\s\\w{3}\\s\\d{2}\\s\\d{2}:\\d{2}:\\d{2}\\s?(.*)\\s\\d{4}$");
Matcher matcher = pattern.matcher(date);
if (matcher.matches()) {
String timezone = matcher.group(1);
// beware : according to the Date.toString() documentation the timezone
// value can be empty
System.out.println(timezone);
} else {
System.out.println("doesn't match!");
}
import java.util package and use GregorianCalendar method.
int second, minute, hour;
GregorianCalendar date = new GregorianCalendar();
second = date.get(Calendar.SECOND);
minute = date.get(Calendar.MINUTE);
hour = date.get(Calendar.HOUR);
System.out.println("Current time is "+hour+" : "+minute+" : "+second);
Don't use Date and Time class of java.util package as their methods are deprecated means they may not be supported in future versions of JDK.
Generate String With Offset But No Date and No Time
Your question is inaccurate. A java.util.Date has no time zone (assumes to always be in UTC). The JVM's time zone is applied in the object' toString method and in other formatting code that generates a String representation. Therein lies your solution: use a date-time formatter that generates a String containing only the offset from UTC without the date or the time-of-day portions.
Avoid java.util.Date & .Calendar
Avoid using the bundled java.util.Date and .Calendar classes as they are notoriously troublesome. Instead use either Joda-Time or the new java.time package. Both support time zones as part of a date-time object.
Joda-Time
Here is how to generate a String representation of a DateTime in Joda-Time 2.3.
DateTime dateTime = new DateTime( DateTimeZone.forID( "Asia/Kolkata" ) );
DateTimeFormatter formatter = DateTimeFormat.forPattern( "ZZ" );
String offset = formatter.print( dateTime ); // generates: +05:30
In Joda-Time 2.3 you can ask a DateTime object for its assigned time zone as an object. You may then interrogate the DateTimeZone object.
DateTime dateTime = new DateTime( DateTimeZone.forID( "Asia/Kolkata" ) );
DateTimeZone timeZone = dateTime.getZone();
String id = timeZone.getID();

Date in to UTC format Java

I have a string like this 2013-10-22T01:37:56. I Need to change this string into UTC Date format like this MM/dd/yyyy KK:mm:ss a. I have tried some code but it is not returning the UTC datetime.
My code is
String[] time = itsAlarmDttm.split("T");
String aFormatDate = time[0]+ " "+time[1];
String aRevisedDate = null;
try {
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
final Date dateObj = sdf.parse(aFormatDate);
aRevisedDate = new SimpleDateFormat("MM/dd/yyyy KK:mm:ss a").format(dateObj);
System.out.println(aRevisedDate);
} catch (ParseException e) {
itsLogger.error("Error occured in Parsing the Data Time Object: " +e.getMessage());
} catch (Exception e) {
itsLogger.error("Error occured in Data Time Objecct: " +e.getMessage());
}
I am getting the output is MM/dd/yyyy KK:mm:ss a format. But Not UTC time format.
How to solve this issue?
Try this... Worked for me and printed 10/22/2013 01:37:56 AM Ofcourse this is your code only with little modifications.
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("UTC")); // This line converts the given date into UTC time zone
final java.util.Date dateObj = sdf.parse("2013-10-22T01:37:56");
aRevisedDate = new SimpleDateFormat("MM/dd/yyyy KK:mm:ss a").format(dateObj);
System.out.println(aRevisedDate);
Try to format your date with the Z or z timezone flags:
new SimpleDateFormat("MM/dd/yyyy KK:mm:ss a Z").format(dateObj);
SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
// or SimpleDateFormat sdf = new SimpleDateFormat( "MM/dd/yyyy KK:mm:ss a Z" );
sdf.setTimeZone( TimeZone.getTimeZone( "UTC" ) );
System.out.println( sdf.format( new Date() ) );
What Time Zones?
No where in your question do you mention time zone. What time zone is implied that input string? What time zone do you want for your output? And, UTC is a time zone (or lack thereof depending on your mindset) not a string format.
ISO 8601
Your input string is in ISO 8601 format, except that it lacks an offset from UTC.
Joda-Time
Here is some example code in Joda-Time 2.3 to show you how to handle time zones. Joda-Time has built-in default formatters for parsing and generating String representations of date-time values.
String input = "2013-10-22T01:37:56";
DateTime dateTimeUtc = new DateTime( input, DateTimeZone.UTC );
DateTime dateTimeMontréal = dateTimeUtc.withZone( DateTimeZone.forID( "America/Montreal" );
String output = dateTimeMontréal.toString();
As for generating string representations in other formats, search StackOverflow for "Joda format".
java.time
It’s about time someone provides the modern answer. The modern solution uses java.time, the modern Java date and time API. The classes SimpleDateFormat and Date used in the question and in a couple of the other answers are poorly designed and long outdated, the former in particular notoriously troublesome. TimeZone is poorly designed to. I recommend you avoid those.
ZoneId utc = ZoneId.of("Etc/UTC");
DateTimeFormatter targetFormatter = DateTimeFormatter.ofPattern(
"MM/dd/yyyy hh:mm:ss a zzz", Locale.ENGLISH);
String itsAlarmDttm = "2013-10-22T01:37:56";
ZonedDateTime utcDateTime = LocalDateTime.parse(itsAlarmDttm)
.atZone(ZoneId.systemDefault())
.withZoneSameInstant(utc);
String formatterUtcDateTime = utcDateTime.format(targetFormatter);
System.out.println(formatterUtcDateTime);
When running in my time zone, Europe/Copenhagen, the output is:
10/21/2013 11:37:56 PM UTC
I have assumed that the string you got was in the default time zone of your JVM, a fragile assumption since that default setting can be changed at any time from another part of your program or another programming running in the same JVM. If you can, instead specify time zone explicitly, for example ZoneId.of("Europe/Podgorica") or ZoneId.of("Asia/Kolkata").
I am exploiting the fact that you string is in ISO 8601 format, the format the the modern classes parse as their default, that is, without any explicit formatter.
I am using a ZonedDateTime for the result date-time because it allows us to format it with UTC in the formatted string to eliminate any and all doubt. For other purposes one would typically have wanted an OffsetDateTime or an Instant instead.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601

How do I format a javax.time.Instant as a string in the local time zone?

How do I format a javax.time.Instant as a string in the local time zone? The following translates a local Instant to UTC, not to the local time zone as I was expecting. Removing the call to toLocalDateTime() does the same. How can I get the local time instead?
public String getDateTimeString( final Instant instant )
{
checkNotNull( instant );
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
DateTimeFormatter formatter = builder.appendPattern( "yyyyMMddHHmmss" ).toFormatter();
return formatter.print( ZonedDateTime.ofInstant( instant, TimeZone.UTC ).toLocalDateTime() );
}
Note: We're using the older version 0.6.3 of the JSR-310 reference implementation.
Answering this question wrt the nearly finished JDK1.8 version
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("yyyyMMddHHmmss").withZone(ZoneId.systemDefault());
return formatter.format(instant);
The key is that Instant does not have any time-zone information. Thus it cannot be formatted using any pattens based on date/time fields, such as "yyyyMMddHHmmss". By specifying the zone in the DateTimeFormatter, the instant is converted to the specified time-zone during formatting, allowing it to be correctly output.
An alternative approach is to convert to ZonedDateTime:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
return formatter.format(ZonedDateTime.ofInstant(instant, ZoneId.systemDefault()));
Both approaches are equivalent, however I would generally choose the first if my data object was an Instant.
Why would you expect it to use the local time zone? You're explicitly asking for UTC:
ZonedDateTime.ofInstant(instant, TimeZone.UTC)
Just specify your local time zone instead:
ZonedDateTime.ofInstant(instant, TimeZone.getDefault())
Try this:
String dateTime = DateTimeFormatter.ISO_ZONED_DATE_TIME.format(
ZonedDateTime.ofInstant(instant, ZoneId.systemDefault())
);
This gives:
2014-08-25T21:52:07-07:00[America/Los_Angeles]
You can change the format by using something other than DateTimeFormatter.ISO_ZONED_DATE_TIME as the formatter. DateTimeFormatter has a bunch of predefined formatters, or you can define your own.
The question was about version 0.6.3 of the JSR-310 reference implementation, long before the arrival of Java 8 and the new date library
I gave up on JSR-310 classes DateTimeFormatter and ZonedDateTime and instead resorted to old fashioned java.util.Date and java.text.SimpleDateFormat:
public String getDateTimeString( final Instant instant )
{
checkNotNull( instant );
DateFormat format = new SimpleDateFormat( "yyyyMMddHHmmss" );
Date date = new Date( instant.toEpochMillisLong() );
return format.format( date );
}

Categories

Resources