This question already has answers here:
DateTimeParse Exception
(2 answers)
IST mapped to wrong ZoneId in java.time library
(3 answers)
Closed 5 months ago.
How to convert this string into instant:
String date = "Fri Sep 30 00:00:00 IST 2022";
Exception:
java.time.format.DateTimeParseException: Text 'Fri Sep 30 00:00:00 IST 2022' could not be parsed at index 0
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
at java.base/java.time.LocalDate.parse(LocalDate.java:428)
In DB it is saved in this format
ISODate("2022-09-29T18:30:00.000Z")
But while debugging in IDE it is coming in string format like this: "Fri Sep 30 00:00:00 IST 2022"
Now I want to convert it back to instant
I tried in this way:
DateTimeFormatter DATE_FORMAT_RULE = DateTimeFormatter.ofPattern("MM/dd/yyyy");
String date = "Fri Sep 30 00:00:00 IST 2022";
Instant instant = LocalDate.parse(date, DATE_FORMAT_RULE)
.atStartOfDay()
.toInstant(ZoneOffset.UTC);
The pattern you are using does not match the one of the String. Your pattern cannot parse a two-digit month first because the String starts with an abbreviated day of week, whose abbreviation even depends on the Locale, which you haven't specified, so it will take the system default.
However, you can try to parse it with a different pattern, but I don't think it will get you the desired result… Try DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z uuuu", Locale.ENGLISH) instead of your DateTimeFormatter.ofPattern("MM/dd/yyyy") and see the result. On my machine, it assumes IST to be Iceland Standard Time!
See this example:
public static void main(String[] args) {
// example String
String toBeParsed = "Fri Sep 30 00:00:00 IST 2022";
// first formatter: tries to parse "IST" as ZONE TEXT
DateTimeFormatter dtfZ = new DateTimeFormatterBuilder()
.appendPattern("EEE MMM dd HH:mm:ss")
.appendLiteral(' ')
.appendZoneText(TextStyle.SHORT)
.appendLiteral(' ')
.appendPattern("uuuu")
.toFormatter(Locale.ENGLISH);
// second formatter: tries to parse "IST" as ZONE NAME
DateTimeFormatter dtfz = DateTimeFormatter.ofPattern(
"EEE MMM dd HH:mm:ss z uuuu",
Locale.ENGLISH
);
// parse to a ZonedDateTime with the first formatter
ZonedDateTime zdt = ZonedDateTime.parse(toBeParsed, dtfZ);
// print the result
System.out.println("ZonedDateTime: "
+ zdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
// parse to a ZonedDateTime with the second formatter
ZonedDateTime zdt2 = ZonedDateTime.parse(toBeParsed, dtfz);
// print that, too
System.out.println("ZonedDateTime: "
+ zdt2.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
// convert to an Instant
Instant instant = zdt.toInstant();
// print the epoch millis
System.out.println(instant.toEpochMilli());
}
Output:
ZonedDateTime: 2022-09-30T00:00:00Z[Atlantic/Reykjavik]
ZonedDateTime: 2022-09-30T00:00:00Z[Atlantic/Reykjavik]
1664496000000
If you want the LocalDate.atStartOfDay(), you could simply extract it by calling toLocalDate() on an instance of ZonedDateTime (in case that ZonedDateTime contains any time of day different from zero hours, minutes, seconds and further down the units).
Corresponding to 2022-09-29T18:30:00.000Z, the IST in Fri Sep 30 00:00:00 IST 2022 refers to Indian Standard Time which has a time offset of UTC+05:30. You can build a formatter using .appendZoneText(TextStyle.SHORT, Set.of(ZoneId.of("Asia/Kolkata"))) with DateTimeFormatterBuilder as shown in the demo below:
public class Main {
public static void main(String[] args) {
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("EEE MMM dd HH:mm:ss")
.appendLiteral(' ')
.appendZoneText(TextStyle.SHORT, Set.of(ZoneId.of("Asia/Kolkata")))
.appendLiteral(' ')
.appendPattern("uuuu")
.toFormatter(Locale.ENGLISH);
Instant instant = ZonedDateTime.parse("Fri Sep 30 00:00:00 IST 2022", formatter).toInstant();
System.out.println(instant);
}
}
Output:
2022-09-29T18:30:00Z
Learn more about the the modern date-time API from Trail: Date Time.
Works for me
DateTimeFormatter DATE_FORMAT_RULE = DateTimeFormatter.ofPattern("E MMM dd hh:mm:ss z yyyy", Locale.US);
String date = "Fri Sep 30 00:00:00 IST 2022";
Instant instant2 = LocalDate.parse(date, DATE_FORMAT_RULE)
.atStartOfDay()
.toInstant(ZoneOffset.UTC);
Related
This question already has answers here:
DateTimeParse Exception
(2 answers)
Closed 2 years ago.
I've tried several methods with Java Joda Time, Date Time with locale and commons-lang and can't get this date formatted.
Input
Mon Dec 28 15:18:16 UTC 2020
Output
Desired output format yyyy-MM-dd HH:mm:ss.SSS
When I use a format pattern like EEE MMM dd HH:mm:ss Z YYYY the date is off my a couple days and the timezone seems completely wrong.
Formatter:
private static final DateTimeFormatter DATE_TIME_FORMATTER =
DateTimeFormatter
.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")
.withLocale(Locale.US)
.withZone(ZoneId.systemDefault());
DateUtils.parseDate (Optional
.ofNullable(record)
.map(CustomerModel::getCustomerAudit)
.map(customerAudit::getCreated)
.map(auditItem::getDate).get ().toString (), "EEE MMM dd HH:mm:ss YYYY")
When debugging parsing issues, if possible, reverse the operation and generate the text you're supposed to be parsing, to verify the parsing rules, i.e. the date format string. This applies to date parsing, JAXB parsing, and any other (de)serializing operation that is bi-directional. It makes finding conversion rule issues a lot easier.
So, let us check the format string in the question, with the shown date value:
ZonedDateTime dateTime = ZonedDateTime.of(2020, 12, 28, 15, 18, 16, 0, ZoneOffset.UTC);
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss Z YYYY", Locale.US);
System.out.println(dateTime.format(fmt));
Output
Mon Dec 28 15:18:16 +0000 2021
Oops! That doesn't fit the expected output, aka the input we desire to parse:
Mon Dec 28 15:18:16 UTC 2020
So what went wrong?
The year is wrong because it's supposed to be uuuu (year), not YYYY (week-based-year).
The time zone is wrong because Z does support a text representation. Use VV or z instead.
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z uuuu", Locale.US);
ZonedDateTime dateTime = ZonedDateTime.parse("Mon Dec 28 15:18:16 UTC 2020", fmt);
System.out.println(dateTime);
System.out.println(dateTime.format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS")));
Output
2020-12-28T15:18:16Z[UTC]
2020-12-28 15:18:16.000
As you can see, it now parsed correctly.
The code in the question makes little sense:
It is formatting a Date value to text using toString(), just to attempt parsing that back.
It is using Optional for simple null-handling (which is discouraged), but then unconditionally calling get(), which means a null value will throw exception anyway.
The code should be:
record.getCustomerAudit().getCreated().getDate().toInstant()
This of course makes the entire question moot.
Works fine for me.
String s = "Mon Dec 28 15:18:16 UTC 2020";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss VV yyyy",
Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(s, formatter);
formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
System.out.println(zdt.format(formatter));
Output is
2020-12-28 15:18:16.000
Am I missing something?
Have you tried with SimpleDateFormat?
String dateString = "Mon Dec 28 15:18:16 UTC 2020";
SimpleDateFormat input = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
SimpleDateFormat output = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
System.out.println(output.format(input.parse(dateString)));
With timezone:
String dateString = "Mon Dec 28 15:18:16 UTC 2020";
SimpleDateFormat input = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
SimpleDateFormat output = new SimpleDateFormat("yyyy-MM-dd z HH:mm:ss.SSS");
input.setTimeZone(TimeZone.getTimeZone("UTC"));
output.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(output.format(input.parse(dateString)));
I am updating my old date formatting code to Java 8 and trying the ZonedDateTime API.
The format of date is same as the Javascript Date object format, e.g. -
Thu May 25 2017 10:00:00 GMT+1200 (New Zealand Standard Time)
I was using the below format previously -
EEE MMM dd yyyy hh:mm:ss 'GMT'Z '('zzzz')'
This format fails to parse the date string using DateTimeFormatter.ofPattern method.
Here's the code:
public static final String DATE_FORMAT = "EEE MMM dd yyyy hh:mm:ss 'GMT'Z '('zzzz')'";
public static void main(String[] args) throws ParseException {
String sDate = "Thu May 25 2017 10:00:00 GMT+1200 (New Zealand Standard Time)";
parseDate(sDate);
}
private static void parseDate(String sDate) throws ParseException {
// works
DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
Date oldDate = dateFormat.parse(sDate);
//FIXME: can't parse?!
ZonedDateTime newDate = ZonedDateTime.parse(
sDate, DateTimeFormatter.ofPattern(DATE_FORMAT)); // <- this is the line 25!
}
Here's my full code for reference that can be compiled and run - https://gist.github.com/bhabanism/470e03db54981ad6ddedbba316dcaa9a
This fails at line#25 with:
Exception in thread "main" java.time.format.DateTimeParseException:
Text 'Thu May 25 2017 10:00:00 GMT+1200 (New Zealand Standard Time)'
could not be parsed: Unable to obtain ZonedDateTime from
TemporalAccessor: {HourOfAmPm=10, MilliOfSecond=0, MinuteOfHour=0,
OffsetSeconds=43200, MicroOfSecond=0, NanoOfSecond=0,
SecondOfMinute=0},ISO,Pacific/Auckland resolved to 2017-05-25 of type
java.time.format.Parsed
Note, I can't change the input format of the Date, it has to be
Thu May 25 2017 10:00:00 GMT+1200 (New Zealand Standard Time)
I can surely modify the formatter
EEE MMM dd yyyy hh:mm:ss 'GMT'Z '('zzzz')'
It seems there was a bug in your format string all the time. Lowercase hh is for hour within AM or PM, in the range 1 through 12. Since you don’t have AM/PM in your string, I suspect this was never what you wanted, and I wonder how the error went unnoticed.
Uppercase HH is for hour of day, 0 through 23:
public static final String DATE_FORMAT = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z '('zzzz')'";
With this change both the old and the new way of parsing works on my computer.
When adding Locale.ENGLISH to both formatters, that is. You may want to do the same.
The results I get are
Thu May 25 00:00:00 CEST 2017
2017-05-25T10:00+12:00[Pacific/Auckland]
Since CEST is 2 hours ahead of UTC, this is the same point in time, only rendered differently.
I m getting follwing error:
val formatter = ISODateTimeFormat.dateTimeParser()
scala> val date2 = "Tue Dec 29 11:11:30 IST 2015"
date2: String = Tue Dec 29 11:11:30 IST 2015
scala> formatter.parseDateTime(date2)
java.lang.IllegalArgumentException: Invalid format: "Tue Dec 29 11:11:30 IST 2015" is malformed at "ue Dec 29 11:11:30 IST 2015"
how to resolve following error??
I think you have the wrong format here - using SimpleDateFormat and a bit of googling this works:
scala> val formatter = new java.text.SimpleDateFormat("EEE MMM d HH:mm:ss Z yyyy")
formatter: java.text.SimpleDateFormat = java.text.SimpleDateFormat#73342172
scala> formatter.parse("Tue Dec 29 11:11:30 IST 2015")
res1: java.util.Date = Tue Dec 29 09:11:30 GMT 2015
edit: errr don't forget the timezone and year like I originally did ;-)
First thing to note:
Your input is not in ISO-Format and contains the name of a timezone (here: IST). You tried Joda-Time, but used an ISO-Format. This cannot work because the ISO-format pattern does not match the non-ISO-input. Second reason against Joda-Time is the fact that Joda-Time cannot parse timezone names. So following approach using a theoretically correct pattern will fail:
String input = "Tue Dec 29 11:11:30 IST 2015";
DateTimeFormatter dtf =
DateTimeFormat.forPattern("EEE MMM d HH:mm:ss z yyyy").withLocale(Locale.ENGLISH);
DateTime unparseable = dtf.parseDateTime(input);
// java.lang.IllegalArgumentException:
// Invalid format: "Tue Dec 29 11:11:30 IST 2015" is malformed at "IST 2015"
So you can only change the library. An obvious candidate using the (horrible) class SimpleDateFormat is:
String input = "Tue Dec 29 11:11:30 IST 2015";
String pattern = "EEE MMM d HH:mm:ss z yyyy";
SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.ENGLISH);
java.util.Date jud = sdf.parse(input);
System.out.println(jud); // Tue Dec 29 10:11:30 CET 2015 (in my local tz CET=+01:00)
Okay no exception. But this does not mean that the result is automatically correct. The result can only be explained by having an offset of (+02:00 for IST). But is this true??? So let's have a closer look at the timezone involved:
TimeZone india = TimeZone.getTimeZone("Asia/Kolkata");
TimeZone israel = TimeZone.getTimeZone("Asia/Jerusalem");
System.out.println(israel.getDisplayName(false, TimeZone.SHORT)); // IST
System.out.println(india.getDisplayName(false, TimeZone.SHORT)); // IST
System.out.println(israel.getOffset(jud.getTime()) / 1000); // 7200 = +02:00
System.out.println(india.getOffset(jud.getTime()) / 1000); // 19800 = +05:30
This should trigger an alarm. Timezone names (especially abbreviations, here: IST) are often ambivalent and denote different timezones with different offsets.
So if you have got the input from Israel then you can be happy, but if from India then the result is wrong by 3:30 hours. Maybe your result will be such that it will match the India case instead of Israel. This will depend on your local timezone configuration. What so ever, don't blindly trust the parsed offsets.
The alternative Java-8:
String input = "Tue Dec 29 11:11:30 IST 2015";
ZoneId india = ZoneId.of("Asia/Kolkata");
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
builder.appendPattern("EEE MMM d HH:mm:ss ");
builder.appendZoneText(TextStyle.SHORT, Collections.singleton(india)); // preferred zone
builder.appendPattern(" yyyy");
DateTimeFormatter dtf = builder.toFormatter(Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(input, dtf);
System.out.println(zdt); // 2015-12-29T11:11:30+05:30[Asia/Kolkata]
// compare dangerous standard approach (not specifying your zone preference)
String pattern = "EEE MMM d HH:mm:ss z yyyy";
zdt = ZonedDateTime.parse(input, DateTimeFormatter.ofPattern(pattern, Locale.ENGLISH));
System.out.println(zdt); // 2015-12-29T11:11:30+02:00[Asia/Jerusalem]
It will work if you specify your preferred timezone but you really need to think twice before you parse timezone names. The builder approach might appear a little bit awkward but cannot be avoided due to the difficulty of the problem. So Java-8 is very fine to give you a solution here.
By the way, if you use a strict style (DateTimeFormatter.ofPattern(pattern, Locale.ENGLISH).withResolverStyle(ResolverStyle.STRICT)) then the parser will throw an exception with the message:
java.time.format.DateTimeParseException: Text 'Tue Dec 29 11:11:30 IST
2015' could not be parsed: Unable to obtain ZonedDateTime from
TemporalAccessor: {YearOfEra=2015, DayOfMonth=29, DayOfWeek=2,
MonthOfYear=12},ISO,Asia/Jerusalem resolved to 11:11:30 of type
java.time.format.Parsed
The message is somehow mysterious but I assume it is because of the ambivalent name IST.
If you are working on a platform with older JDK (Java 6 or 7) then you might consider ThreetenBP. ThreetenBP has the advantage to make a future migration easy (just changing the import statements) but my own experiments with the builder approach failed, unfortunately (even failed with the newest version v1.3.1 - maybe this depends on the underlying JDK???):
String input = "Tue Dec 29 11:11:30 IST 2015";
ZoneId india = ZoneId.of("Asia/Kolkata");
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
builder.appendPattern("EEE MMM d HH:mm:ss ");
builder.appendZoneText(TextStyle.SHORT, Collections.singleton(india)); // preferred zone
builder.appendPattern(" yyyy");
DateTimeFormatter dtf = builder.toFormatter(Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(input, dtf);
System.out.println(zdt); // 2015-12-29T11:11:30+02:00[Israel] // why???
Else you can try my library Time4J which works on Java-6 or 7 (or later). It works similar to Java-8:
String input = "Tue Dec 29 11:11:30 IST 2015";
TZID india = ASIA.KOLKATA;
ChronoFormatter<Moment> f = ChronoFormatter.setUp(Moment.axis(), Locale.ENGLISH)
.addPattern("EEE MMM d HH:mm:ss ", PatternType.CLDR)
.addShortTimezoneName(Collections.singleton(india)) // preferred zone
.addPattern(" yyyy", PatternType.CLDR)
.build();
System.out.println(f.parse(input)); // 2015-12-29T05:41:30Z
System.out.println(ZonalDateTime.parse(input, f)); // 2015-12-29T11:11:30UTC+05:30[Asia/Kolkata]
The error message in strict or smart parser style using
String input = "Tue Dec 29 11:11:30 IST 2015";
String pattern = "EEE MMM d HH:mm:ss z yyyy";
ChronoFormatter<Moment> f = // here smart standard style!
ChronoFormatter.ofMomentPattern(
pattern, PatternType.CLDR, Locale.ENGLISH, ZonalOffset.UTC);
f.parse(input);
will be:
Time zone name "IST" not found among preferred timezones in locale en,
candidates=[Asia/Colombo, Asia/Jerusalem, Asia/Kolkata, Europe/Dublin]
Then you will immediately see that "IST" can be associated with different timezones.
I have got the following created date "Fri Jan 24 12:22:13 +0000 2014" from twitter , but when it comes to parsing , the goes to unparsable exception error at "z"
Would you please tell em what is the correct time format ?
The below is my code
String dateString = fullS.substring(0, 11) + " "+ year;
String timeZoneHK = content.getTimeZone();
SimpleDateFormat inputDf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
SimpleDateFormat outputDf = new SimpleDateFormat("HH:mm:ss EEE MMM dd yyyy");
Date date;
try {
TimeZone timezone = null;
date = inputDf.parse(dateString);
if(timeZoneHK.equals("Hong Kong")){
timezone = TimeZone.getTimeZone("Asia/Hong_Kong");
}
outputDf.setTimeZone(timezone);
String result =outputDf.format(date);
//System.out.println(outputDf.format(date));
viewHolder.txtDate.setText(result);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Exception
01-24 22:10:30.061: W/System.err(12573): java.text.ParseException: Unparseable date: "Fri Jan 24 13:37:08 +0000 2014" (at offset 0)
Use complete date String "Fri Jan 24 12:22:13 +0000 2014" if wanted to apply the specified format. And change z to Z:
SimpleDateFormat inputDf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");
Refer to: SimpleDateFormat
Z - time zone (RFC 822) - (Time Zone) Z/ZZ/ZZZ:-0800 - ZZZZ:GMT-08:00 ZZZZZ:-08:00
Joda-Time
This kind of work is much easier with the third-party open-source date-time library, Joda-Time.
Here is some example code using Joda-Time 2.3.
String input = "Fri Jan 24 12:22:13 +0000 2014";
DateTimeFormatter formatter = DateTimeFormat.forPattern( "EEE MMM dd HH:mm:ss Z yyyy" );
// Parse as UTC/GMT (no time zone offset) so we may conveniently compare to input.
DateTime dateTimeUtc = formatter.withZone( DateTimeZone.UTC ).parseDateTime( input );
// Convert to Hong Kong time zone.
DateTime dateTimeHongKong = dateTimeUtc.toDateTime( DateTimeZone.forID( "Asia/Hong_Kong" ) );
Dump to console…
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "dateTimeHongKong: " + dateTimeHongKong );
When run…
dateTimeUtc: 2014-01-24T12:22:13.000Z
dateTimeHongKong: 2014-01-24T20:22:13.000+08:00
Back To Date
If you need a java.util.Date for other purposes, convert your DateTime.
java.util.Date date = dateTime.toDate();
I have a date String "Sat Jan 28 00:00:00 IST 2012" and I am trying to parse it using DateTimeFormatter of Joda. I have the following code, dont know where, it went wrong.
DateTimeFormatter dateFmt = DateTimeFormat
.forPattern("EEE MMM dd HH:mm:SS ZZZ yyyy");
DateTime dateTime = dateFmt.parseDateTime(dateString);
Exception : java.lang.IllegalArgumentException: Invalid format: "Sat Jan 28 00:00:00 IST 2012" is malformed at "IST 2012". Please help me to get thro this. Thanks for any help.
IST is not recognized timezone by API, It can recognize only one of the timezone from getAvailableIds()
Use zzz (lowercase), not ZZZ (uppercase). From the API docs:
z time zone text Pacific Standard Time; PST
Z time zone offset/id zone -0800; -08:00; America/Los_Angeles
I don't know why, but it is working if I use SimpleDateFormat instead of DateTimeFormatter.
CODE:
public static void main(String[] args) throws ParseException {
String FORMAT = "EEE MMM dd HH:mm:SS zzz yyyy";
String dateString = "Sat Jan 28 00:00:00 IST 2012";
SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT);
Date date = dateFormat.parse(dateString);
System.out.println(new DateTime(date));
DateTimeFormatter dateFmt = DateTimeFormat.forPattern(FORMAT);
// System.out.println(dateFmt.parseLocalDateTime(dateString));
// System.out.println(dateFmt.parseDateTime(dateString));
System.out.println(dateFmt.parseLocalTime(dateString));
}