How to solve Invalid Date format error in scala? - java

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.

Related

How to convert Sting into instant in Java [duplicate]

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);

Java DateTimeFormatter: DateTimeParseException with GMT-date

I would like to parse an GMT-date like Wed, 21 Oct 2016 07:28:00 GMTwith DateTimeFormatter into an Instant. To create the pattern i used the official documentation: DateTimeFormatter
My code so far:
String date = "Wed, 21 Oct 2016 07:28:00 GMT";
DateTimeFormatter gmtFormat = DateTimeFormatter.ofPattern("EEE' dd LLL yyyy HH:mm:ss '''");
TemporalAccessor parsed = gmtFormat.parse(date);
Instant a = Instant.from(parsed);
System.out.println(a);
But every time i've got this error:
Exception in thread "main" java.time.format.DateTimeParseException: Text 'Wed, 21 Oct 2016 07:28:00 GMT' could not be parsed at index 0
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1777)
At index 0 is Wed, I used EEE which represents day-of-week by definition, there are also examples which represent: Tue; Tuesday; T.
I've also tried lower-, and uppercase but not successfully. What is wrong? Did I overlook something?
It works with the code
String date = "Fri, 21 Oct 2016 07:28:00 GMT";
DateTimeFormatter gmtFormat = DateTimeFormatter.RFC_1123_DATE_TIME;
TemporalAccessor parsed = gmtFormat.parse(date);
Instant a = Instant.from(parsed);
System.out.println(a);
But you have to change the day because otherwise it doesn't fit to the given date.
EEE is the proper format for Wed. But it does not include the comma.
Try this:
DateTimeFormatter gmtFormat = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss '''");
Useful link
You're asking for redundant information: The day of the week and the date.
Change the format to just ignore the first three characters, leaving it reading the day/month/year.

Old Date Formatting incompatible with Java 8 ZonedDateTime API

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.

Can't convert string to date in Java, wrong timezone after conversion

I have an array of Strings with the dates e.g.:
Tue, 09 Feb 2016 14:07:00 GMT;
Tue, 09 Feb 2016 19:55:00 GMT.
Now I want to find the most recent date on this list. In order to do that, I try to deserialize these strings to java.util.Date objects and after that compare them.
The code sample of java.util.Date object generation:
strDate = "Tue, 09 Feb 2016 14:07:00 GMT";
DateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
Date date;
try {
date = format.parse(strDate);
//Result: Tue Feb 09 16:07:00 IST 2016
System.out.println("Result: " + date.toString());
} catch(ParseException e) {
e.printStackTrace();
}
My questions:
Why is the result in IST 2016 time zone and not in GMT? What does the IST 2016 stand for? Is it India Standard Time or Irish Standard Time or Israel Standard Time?
The initial string is in EEE, dd MMM format, the SimpleDateFormat pattern is also in this format, thus, why the result is in EEE, MMM dd format?
How can get a java.util.Date object in the same timezone as the initial string, in my case — GMT?
Is the approach I'm using to find the most recent date in the list is OK or there is more convenient/modern way to do that in Java 8, e.g., with the usage of LocalDateTime?
You are relying to Date.toString() to print your date when you should format it to a String with a formatter. What you are seeing is just the default pattern of Date.toString(). What you must keep in mind is that a Date does not have a timezone. You are seeing the output with the IST timezone, this must be because the current locale for the JVM is set to some specific locale for which the timezone name is "IST".
With regard to your point 4, yes, you can do it much cleaner with Java Time API introduced in Java 8. You can create a List of your strings to parse, create a DateTimeFormatter to parse it, and keep the maximum date value.
public static void main(String[] args) {
List<String> dates = Arrays.asList("Tue, 09 Feb 2016 14:07:00 GMT", "Tue, 09 Feb 2016 19:55:00 GMT");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
ZonedDateTime maxDate = dates.stream()
.map(s -> ZonedDateTime.parse(s, formatter))
.max(ZonedDateTime::compareTo)
.get(); // or .orElse(null)
System.out.println(maxDate);
}
This code is using a ZonedDateTime to keep the time-zone of the incoming strings.
Your computer seems to be set to IST. To force GMT output, import java.util.TimeZone and do this in your try block:
format.setTimeZone(TimeZone.getTimeZone("GMT"));
date = format.parse(strDate);
System.out.println("Result: " + format.format(date));

how to convert date in java

I am new in android .
I have to convert following date into this time stamp (Wed Oct 12 14:17:42 GMT+05:30 2011)
Thu, 27 May 2010 12:37:27 GMT
This is the date that I am getting from the server through the header. I have converted it into the String object. Now I have to convert it into the Date format like: Wed Oct 12 14:17:42 GMT+05:30 2011
Please could you help me how should I convert it into the (Wed Oct 12 14:17:42 GMT+05:30 2011) this format using timestamp.
Have a look at DateFormat or SimpleDateFormat which provide parse() and format() methods. DateFormat provides a bunch of standard formats whereas SimpleDateFormat allows you to provide your own format expression.
Example for your input date:
//note that you need the locale as well, since the weekdays and months are written in a specific language, English in that case
SimpleDateFormat parseFormat = new SimpleDateFormat( "E, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH );
SimpleDateFormat writeFormat = new SimpleDateFormat( "E MMM dd HH:mm:ss z yyyy", Locale.ENGLISH );
writeFormat.setTimeZone( TimeZone.getTimeZone( "GMT" ) );
Date tDate = parseFormat.parse( "Wed, 12 Oct 2011 14:17:42 GMT" );
System.out.println(writeFormat.format(tDate )); //Wed Oct 12 14:17:42 GMT 2011
Edit: If you want a more usable API, try JodaTime.

Categories