parsing dates with variable spaces - java

I am using Joda to parse dates and have a format where leading zeros are not used, e.g.:
Mon Nov 20 14:40:36 2006
Mon Nov 6 14:40:36 2006
Note that the dayOfMonth field is left-padded with a blank.
Currently I seem to have to use two different formats and reparse if one fails
"EEE MMM dd HH:mm:ss yyyy"
"EEE MMM d HH:mm:ss yyyy"
Is there a single format (or an API switch) which deals with both cases? (is the answer the same for SimpleDateFormat - which I don't use?)

java.time and format pattern letter p
Here’s the modern answer, using java.time, the successor of Joda-Time.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM ppd HH:mm:ss uuuu", Locale.ENGLISH);
String[] stringsToParse = {
"Mon Nov 20 14:40:36 2006",
"Mon Nov 6 14:40:36 2006"
};
for (String dateTimeString : stringsToParse) {
LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, formatter);
System.out.println(dateTime);
}
Output:
2006-11-20T14:40:36
2006-11-06T14:40:36
To DateTimeFormatter.ofPattern format letter p means padding with spaces on the left. pp means padding to two position. It can be used for both formatting and — as here — parsing.
I know you asked about Joda-Time. The Joda-Time home page says:
Note that Joda-Time is considered to be a largely “finished” project.
No major enhancements are planned. If using Java SE 8, please migrate
to java.time (JSR-310).
Links
Oracle tutorial: Date Time explaining how to use java.time.
Documentation of DateTimeFormatter
Joda-Time - Home

I have just created a quick program to check this -
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy");
try {
String source1 = "Mon Nov 20 14:40:36 2006";
Date d1 = sdf.parse(source1);
String source2 = "Mon Nov 6 14:40:36 2006";
Date d2 = sdf.parse(source2);
String res1 = sdf.format(d1);
String res2 = sdf.format(d2);
System.out.println(source1 +"="+ res1);
System.out.println(source2 +"="+ res2);
} catch (ParseException e) {
e.printStackTrace();
}
The output from this is -
Mon Nov 20 14:40:36 2006=Mon Nov 20 14:40:36 2006
Mon Nov 6 14:40:36 2006=Mon Nov 6 14:40:36 2006
So, even though source2 has the extra space, it is still parsed by
EEE MMM d HH:mm:ss yyyy
Hope that helps

I tried using a single 'd' as suggested above in logstash 1.1.1 but it still complained about a malformed date when a single digit day with an extra leading space was parsed. The following logstash rules did work.
timestamp => [ "MMM dd HH:mm:ss", "MMM d HH:mm:ss" ]
It didn't matter which order the two date formats were in. No more warnings were output once I added both formats.

Related

Java (not JavaScript) Date parsing issue: java.text.ParseException

I've got a problem with the following date format: "Jan 15 2020 11:11:50.000 +0000". I need to parse the date into ms.
The odd behavior is that i can't use date.parse(). The function is always failing with "java.text.ParseException: Unparseable date: "Jan 15 2020 11:11:50.000 +0000";".
Someone got an idea how to manually parse the date or to change the date format within date.parse()?
Thanks all
With a ZonedDateTime and this pattern LLL d yyyy HH:mm:ss.SSS Z (DateTimeFormatter) you'll be able to handle it
String value = "Jan 15 2020 11:11:50.000 +0000";
DateTimeFormatter dt = DateTimeFormatter.ofPattern("LLL d yyyy HH:mm:ss.SSS Z", Locale.ENGLISH);
ZonedDateTime l = ZonedDateTime.parse(value, dt);
System.out.println(l.format(dt)); // Jan 15 2020 11:11:50.000 +0000

java.text.ParseException: Unparseable date: "Wed Mar 11 2020"

The full date received from the request is of this format
Wed Mar 11 2020 05:29:01 GMT+0100 (West Africa Standard Time)
Now I substringed it to this - Wed Mar 11 2020
date.substring(0,15))
To enable me to save the date, I am parsing it as below
SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-dd", Locale.ENGLISH);
Date parsedDate = null;
try {
parsedDate = format.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
When the code is ran, I get below error
java.text.ParseException: Unparseable date: "Wed Mar 11 2020"
I have also tried parsing with
SimpleDateFormat format = new SimpleDateFormat("EE MMM dd HH:mm:ss z yyyy",
Locale.ENGLISH);
based on SO answers and I am still getting date parsing error.
How can I parse this date - date.substring(0,15))
The format you need to match your date is EEE MMM dd yyyy e.g.
String date = "Wed Mar 11 2020 05:29:01 GMT+0100 (West Africa Standard Time)";
date = date.substring(0,15);
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd yyyy");
Date parsedDate = null;
try {
parsedDate = format.parse(date);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(parsedDate);
SimpleDateFormat outformat = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(outformat.format(parsedDate));
Output:
Wed Mar 11 00:00:00 CET 2020
2020-03-11
Three points:
Do use java.time, the modern Java date and time API, for your date and time work.
Rather than taking a substring of the string you receive, I’d prefer to parse the entire string.
Your format pattern string must match the string you are trying to parse (and vice versa). Exactly.
In code:
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern(
"EEE MMM d uuuu HH:mm:ss 'GMT'xx (zzzz)", // Pattern to match your input strings.
Locale.UK // Locale determines human language used to parse name of month and such.
)
;
String dateString = "Wed Mar 11 2020 05:29:01 GMT+0100 (West Africa Standard Time)";
ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateString, formatter);
Generate a string.
System.out.println( zonedDateTime.toString() );
Output from this snippet is:
2020-03-11T03:29:01+01:00[Africa/Lagos]
Use java.time. The modern API is sol much nicer to work with. The Date class that you used is poorly designed, and SimpleDateFormat notoriously troublesome. Don’t use any of those.
Parse the entire string. Taking a substring of length 15 will cause some readers of your code to wonder, some ask “WTF?”, some to use their precious time for counting to make sure that 15 is the correct length. Also taking a substring of length 15 is fragile unless you’re sure that the abbreviations for day of week and for month always have length three and day of month is always written with two digits (May 02, not May 2). Furthermore it’s easier to parse more than you need and throw information away later, than to parse just what you think you need and later discover that you needed one more bit.
Specifying the format. Since your string begins with a day of week abbreviation, you need a format pattern string that begins with the format pattern letter for day of week. In this case EEE (or E or EE) for the abbreviation (EEEE would have meant the day written in full, like Wednesday). So YYYY-MM-dd is all wrong. EE MMM dd HH:mm:ss z yyyy comes closer and can parse day of week, month and day of month. Then comes a space and a year in the input, but your format pattern string has yyyy for year at the end instead, so this is where parsing breaks for you. If writing the correct format pattern string teases (as it does for many), a trick is to try something and first use the formatter for formatting a date and time. If the result differs from the string we would like to parse, it usually gives us a hint about what’s wrong.
Link: Oracle tutorial: Date Time explaining how to use java.time.
Try this.
SimpleDateFormat sdf3 = new SimpleDateFormat("EEE MMM dd yyyy");
Date d1 = null;
try {
d1 = sdf3.parse("Wed Mar 30 2016");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(sdf3.format(d1));
}
Output:
Wed Mar 30 2016
First you need to control your computer language. According to your computer's language. You must write day's name and month's name in your computer's language
Actually you had better convert this 'Wed' according to your language.
My computer's language is turkish.
I used below code how to use day's name on date on java.
public static void main(String[] args) {
String sDate1 = "Per Mar-11-2020";
String sDate2 = "Perşembe Mar-11-2020";
Date date1;
try {
date1 = new SimpleDateFormat("EEE MMM-dd-yyyy").parse(sDate1);
System.out.println(sDate1+"\t\t"+date1);
date1 = new SimpleDateFormat("EEEEE MMM-dd-yyyy").parse(sDate2);
System.out.println(sDate2+"\t\t"+date1);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
output :
Per Mar-11-2020 Wed Mar 11 00:00:00 AST 2020
Perşembe Mar-11-2020 Wed Mar 11 00:00:00 AST 2020
Also you need to be carefull such as :
if your String is Per Mar-11-2020, you need to write EEE MMM-dd-yyyy.
Or
if your String is Per Mar 11 2020, you need to write EEE MMM dd yyyy.
Or
if your String is Per Mar/11/2020, you need to write EEE MMM/dd/yyyy.

Getting incorrect parsed date when using SimpleDateTimeFormatter with time zone

I've the following code:
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
String s2 = "Mon Oct 19 19:52:21 IST 2015";
System.out.println(format.parse(s2));
I expected that the code would print "Mon Oct 19 07:22:21 PDT 2015", but to my surprise it printed "Mon Oct 19 10:52:21 PDT 2015". I can see that "IST" is a valid time zone for "z". However, the following code worked fine:
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
String s2 = "Mon Oct 19 19:52:21 GMT+05:30 2015";
System.out.println(format.parse(s2));
Please help.
Using IST is dangerous as it could stand for Indian or Israel ST.
Assuming you meant Indian ST, try this:
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
format.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
String s2 = "Mon Oct 19 19:52:21 IST 2015";
System.out.println(format.parse(s2));
Also, follow suggestion from #Meno's answer
The code expression
System.out.println(format.parse(s2));
always prints your instant/moment (an object of type java.util.Date) in your system timezone which is apparently PDT. You implicitly apply the method toString()on java.util.Date. Use a dedicated formatter like SimpleDateFormat and set the timezone on this formatter to achieve the desired result.
Finally you need two formatters, one for parsing and one for printing.

Parse a String to Date in Java

I'm trying to parse a string to a date, this is what I have:
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss zZ (zzzz)");
Date date = new Date();
try {
date = sdf.parse(time);
} catch (ParseException e) {
e.printStackTrace();
}
the string to parse is this:
Sun Jul 15 2012 12:22:00 GMT+0300 (FLE Daylight Time)
I followed the http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
Pretty sure I've done everything by the book. But it is giving me ParseException.
java.text.ParseException: Unparseable date:
"Sun Jul 15 2012 12:22:00 GMT+0300 (FLE Daylight Time)"
What am I doing wrong? Patterns I Have tried:
EEE MMM dd yyyy HH:mm:ss zzz
EEE MMM dd yyyy HH:mm:ss zZ (zzzz)
You seem to be mixing the patterns for z and Z. If you ignore the (FLE Daylight Time), since this is the same info as in GMT+0300, the problem becomes that SimpleDateFormat wants either GMT +0300 or GMT+03:00. The last variant can be parsed like this:
String time = "Sun Jul 15 2012 12:22:00 GMT+03:00 (FLE Daylight Time)";
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss zzz");
Date date = sdf.parse(time);
[EDIT]
In light of the other posts about their time strings working, this is probably because your time string contains conflicting information or mixed formats.
java.time
I should like to contribute the modern answer. Use java.time, the modern Java date and time API, for your date and time work.
First define a formatter for parsing:
private static final DateTimeFormatter PARSER = DateTimeFormatter
.ofPattern("EEE MMM dd yyyy HH:mm:ss 'GMT'Z (", Locale.ROOT);
Then parse in this way:
String time = "Sun Jul 15 2012 12:22:00 GMT+0300 (FLE Daylight Time)";
TemporalAccessor parsed = PARSER.parse(time, new ParsePosition(0));
OffsetDateTime dateTime = OffsetDateTime.from(parsed);
System.out.println(dateTime);
Output is:
2012-07-15T12:22+03:00
I am not parsing your entire string, but enough to establish a point in time and an offset from GMT (or UTC). Java cannot parse the time zone name FLE Daylight Time. This is a Microsoft invention that Java does not know. So I parse up to the round bracket before FLE in order to validate this much of the string. To instruct the DateTimeFormatter that it needs not parse the entire string I use the overloaded parse method that takes a ParsePosition as second argument.
From Wikipedia:
Sometimes, due to its use on Microsoft Windows, FLE Standard Time (for
Finland, Lithuania, Estonia, or sometimes Finland, Latvia, Estonia) …
are used to refer to Eastern European Time.
If you indispensably need a Date object, typically for a legacy API that you cannot afford to upgrade to java.time just now, convert like this:
Date oldfashionedDate = Date.from(dateTime.toInstant());
System.out.println(oldfashionedDate);
Output when run in Europe/Tallinn time zone:
Sun Jul 15 12:22:00 EEST 2012
What went wrong in your code?
Your SimpleDateFormat successfully parsed GMT+03 into a “time zone” matching the small z in the format pattern string. It then tried to parse the remaining 00 into an offset to match the capital Z. Since an offset requires a sign, this failed.
What am I doing wrong?
As others have said, you should not try to parse GMT into a time zone abbreviation. GMT can be used as a time zone abbreviation; but your time is not in GMT. So you don’t want that. It would only be misleading. Had you been successful, you would rather have risked an incorrect result because you had parsed a time zone that was incorrect for your purpose.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Eastern European Time on Wikipedia.
Try it this way..
System.out.println(new SimpleDateFormat(
"EEE MMM dd yyyy HH:mm:ss zZ (zzzz)").format(new Date()));
Output i got:
Thu Jul 12 2012 12:41:35 IST+0530 (India Standard Time)
You can try to print the date format string :
/**
* #param args
*/
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat(
"EEE MMM dd yyyy HH:mm:ss zZ (zzzz)");
Date date = new Date();
try {
//
System.out.println(sdf.format(date));
date = sdf.parse(time);
} catch (Exception e) {
e.printStackTrace();
}
}
If you have problems with locales, you can either set the default Locale for the whole application
Locale.setDefault(Locale.ENGLISH);
or just use the english locale on your SimpleDateFormat
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss zZ (zzzz)", Locale.ENGLISH);
You can also use Locale.US or Locale.UK.

Joda-Time DateTimeFormatter: get the correct output

I need to convert a Joda-Time DateTime into a String, in the following format:
Sat, 1 Jan 2011 00:00:00
I'm using this code:
DateTimeFormatter f = DateTimeFormat.forPattern("E, d MMM yyyy HH:mm:ss");
f.withLocale(Locale.US);
System.out.println(DateTime.now().toString(f));
My output is however:
wo, 20 jun. 2012 00:03:31
So the problems are:
The output is in Dutch instead of English ('wo' for 'wed')
The month has a period
How can I do this correctly?
DateTimeFormatter.withLocale returns a new DateTimeFormatter. So you need to do this:
f = f.withLocale(Locale.US);
Alternatively (equivalently):
DateTimeFormatter f = DateTimeFormat.forPattern("E, d MMM yyyy HH:mm:ss").withLocale(Locale.US);

Categories

Resources