Calendar class in Java, ParseException - java

So, I'm experimenting with the Calendar class in Java, and I'm writing a method which returns a Calendar object.
What I want for said method is to return a Calendar object containing "Sun Feb 09 22:49:36 +0000 2014".
Now I'm (debatably) not lazy and I have done some work on my method.
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat(
"EEE MMM dd HH:mm:ss Z yyyy");
try {
cal.setTime(sdf.parse("Sun Feb 09 22:49:36 +0000 2014"));
} catch (ParseException e) {
e.printStackTrace();
}
return cal;
The problem is it keeps telling me that I got a ParseException, that it's an "Unparseable date".
I thought my logic was pretty correct, but I'm starting to doubt it.
I'd prefer it without importing any more than Calendar, but SimpleDateFormat seems to be pretty handy too.
The less imports the better, I always say.
Anyone see how what I want can be achieved?
EDIT 1
Tried to run the code in a main method and just print out the result, with no difference in Exception.
The following is my main:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class TestingMyCalendar {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat(
"EEE MMM dd HH:mm:ss Z yyyy");
try {
cal.setTime(sdf.parse("Sun Feb 09 22:49:36 +0000 2014"));
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(cal);
}
}
For those interested, the following is my entire console text after the main crashed:
java.text.ParseException: Unparseable date: "Sun Feb 09 22:49:36 +0000 2014"
at java.text.DateFormat.parse(Unknown Source)
at TestingMyCalendar.main(TestingMyCalendar.java:15)
java.util.GregorianCalendar[time=1391987659892,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Berlin",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=143,lastRule=java.util.SimpleTimeZone[id=Europe/Berlin,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2014,MONTH=1,WEEK_OF_YEAR=7,WEEK_OF_MONTH=2,DAY_OF_MONTH=10,DAY_OF_YEAR=41,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=2,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=14,SECOND=19,MILLISECOND=892,ZONE_OFFSET=3600000,DST_OFFSET=0]

You may need to set your default locale to Locale.ENGLISH, otherwise the parser might choke on the Sun for Sunday.
Try:
Locale.setDefault(Locale.ENGLISH);
Or, specify it as part of the constructor call:
SimpleDateFormat sdf = new SimpleDateFormat(
"EEE MMM dd HH:mm:ss Z yyyy", Locale.ENGLISH);

Your stacktrace indicates Europe/Berlin as the timezone suggests that you are using a German Locale. The day or month fields may not match those from your default locale, Try
SimpleDateFormat sdf =
new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.ENGLISH);

The other answers are correct. I'll add a few thoughts.
Defaults Are Tricky
Probably the most common source of trouble in date-time work is inadvertently relying on:
Default time zone
Default locale
I've come to the conclusion that both should be specified in all my code, as a habit. I don't want my code changing its behavior (or breaking, as in your case) if it happens to be run with a different time zone or locale setting.
The only case where date-time code should use the default is when you truly want to detect and utilize the user's (the JVM's) own settings for localization. And even in this case, I explicitly make a call to retrieve and use the default rather than rely on the implicit default, so as to make my code obvious and self-documenting.
DateTimeZone.getDefault()
java.util.Locale.getDefault()
Joda-Time
As a commenter said, minimizing your imports is indeed a queer goal. Especially with java.util.Calendar and java.util.Date – If ever there were a case for imports it would be those two classes. They are notoriously troublesome, and should be avoided. Use Joda-Time. Or, in Java 8, use the bundled new java.time.* package, inspired by Joda-Time, defined by JSR 310.
Note that in Joda-Time, a DateTime object truly knows its own assigned time zone. That's a big contrast to java.util.Date which has no assigned time zone but its toString applies the JVM's default time zone which leads to much confusion.
Here is some example code in Joda-Time 2.3.
String input = "Sun Feb 09 22:49:36 +0000 2014";
DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" );
DateTimeFormatter formatter = DateTimeFormat.forPattern( "EEE MMM dd HH:mm:ss Z yyyy" ).withLocale( Locale.ENGLISH ).withZone( timeZone );
DateTime dateTime = formatter.parseDateTime( input );
Dump to console…
System.out.println( "dateTime: " + dateTime );
System.out.println( "Same dateTime in UTC/GMT: " + dateTime.withZone( DateTimeZone.UTC ) );
When run…
dateTime: 2014-02-09T17:49:36.000-05:00
Same dateTime in UTC/GMT: 2014-02-09T22:49:36.000Z

Related

Year end date (java.util.Date) converted to string as wrong date [duplicate]

I am trying to convert EEE MMM dd HH:mm:ss ZZZ yyyy to YYYY-MM-DD format, so I can insert it into a MySQL database. I do not get any error, but the date inserted into my db is wrong and the same for every row...
String date = Sat Mar 04 09:54:20 EET 2017;
SimpleDateFormat formatnow = new SimpleDateFormat("EEE MMM dd HH:mm:ss ZZZ yyyy");
SimpleDateFormat formatneeded=new SimpleDateFormat("YYYY-MM-DD");
java.util.Date date1 = (java.util.Date)formatnow.parse(date);
String date2 = formatneeded.format(date1);
java.util.Date date3= (java.util.Date)formatneeded.parse(date2);
java.sql.Date sqlDate = new java.sql.Date( date3.getTime() );
pst.setDate(1, sqlDate);
LocalDate date4 = ZonedDateTime
.parse(date, DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH))
.toLocalDate();
java.sql.Date date5 = java.sql.Date.valueOf(date4);
I am using the modern classes in the java.time package. You notice that the code is not only simpler, once you get acquainted with the fluent writing style of the newer classes, it is also clearer.
If you wanted to be 100 % modern, you should also check out whether your latest MySQL JDBC driver wouldn’t accept a LocalDate directly without conversion to java.sql.Date. It should.
A few details to note
If you need your code to run on computers outside your control, always give locale to your formatter, or your date string cannot be parsed on a computer with a non-English-speaking locale. You may use Locale.ROOT for a locale neutral locale (it speaks English).
If you can, avoid the three letter time zone abbreviations. Many are ambiguous. EET is really only half a time zone since some places where it’s used are on EEST (summer time) now. Better to use either a long time zone ID like Europe/Bucharest or an offset from UTC like +02:00.
These points are valid no matter if you use DateTimeFormatter or SimpleDateFormat.
If you cannot or do not want to move on to the recommended newer classes, the fix to your code is:
SimpleDateFormat formatnow
= new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH);
SimpleDateFormat formatneeded = new SimpleDateFormat("yyyy-MM-dd");
I am using lowercase zzz since this is documented to match a three-letter time zone name, I know that uppercase ZZZ works too. I have added locale. And maybe most importantly, in the needed format I have changed YYYY (week-based year) to yyyy (calendar year) and DD (day of year) to dd (day of month). All those letters are in the documentation.
I know this question is related to java.sql.Date but as additional information, if you want to convert the date into LocalDate then below code might help:
private LocalDate getLocalDate(String date){
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd hh:mm:ss Z yyyy", Locale.getDefault());
return LocalDate.parse(date, formatter);
}
And once you get the LocalDate, you can transform it to any format. As the question expects yyyy-MM-dd then just call toString() on LocalDate object.
LocalDate curr = LocalDate.now();
System.out.println(curr.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
System.out.println(curr.toString());
It will display the date like "2019-11-20".
Hope this helps to someone.

Different values when parsing date [duplicate]

This question already has answers here:
Java string to date conversion
(17 answers)
Closed 6 years ago.
I am trying to parse this date with SimpleDateFormat and it is not working:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Formaterclass {
public static void main(String[] args) throws ParseException{
String strDate = "Thu Jun 18 20:56:02 EDT 2009";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date dateStr = formatter.parse(strDate);
String formattedDate = formatter.format(dateStr);
System.out.println("yyyy-MM-dd date is ==>"+formattedDate);
Date date1 = formatter.parse(formattedDate);
formatter = new SimpleDateFormat("dd-MMM-yyyy");
formattedDate = formatter.format(date1);
System.out.println("dd-MMM-yyyy date is ==>"+formattedDate);
}
}
If I try this code with strDate="2008-10-14", I have a positive answer. What's the problem? How can I parse this format?
PS. I got this date from a jDatePicker and there is no instruction on how modify the date format I get when the user chooses a date.
You cannot expect to parse a date with a SimpleDateFormat that is set up with a different format.
To parse your "Thu Jun 18 20:56:02 EDT 2009" date string you need a SimpleDateFormat like this (roughly):
SimpleDateFormat parser=new SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy");
Use this to parse the string into a Date, and then your other SimpleDateFormat to turn that Date into the format you want.
String input = "Thu Jun 18 20:56:02 EDT 2009";
SimpleDateFormat parser = new SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy");
Date date = parser.parse(input);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
String formattedDate = formatter.format(date);
...
JavaDoc: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
The problem is that you have a date formatted like this:
Thu Jun 18 20:56:02 EDT 2009
But are using a SimpleDateFormat that is:
yyyy-MM-dd
The two formats don't agree. You need to construct a SimpleDateFormat that matches the layout of the string you're trying to parse into a Date. Lining things up to make it easy to see, you want a SimpleDateFormat like this:
EEE MMM dd HH:mm:ss zzz yyyy
Thu Jun 18 20:56:02 EDT 2009
Check the JavaDoc page I linked to and see how the characters are used.
We now have a more modern way to do this work.
java.time
The java.time framework is bundled with Java 8 and later. See Tutorial. These new classes are inspired by Joda-Time, defined by JSR 310, and extended by the ThreeTen-Extra project. They are a vast improvement over the troublesome old classes, java.util.Date/.Calendar et al.
Note that the 3-4 letter codes like EDT are neither standardized nor unique. Avoid them whenever possible. Learn to use ISO 8601 standard formats instead. The java.time framework may take a stab at translating, but many of the commonly used codes have duplicate values.
By the way, note how java.time by default generates strings using the ISO 8601 formats but extended by appending the name of the time zone in brackets.
String input = "Thu Jun 18 20:56:02 EDT 2009";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "EEE MMM d HH:mm:ss zzz yyyy" , Locale.ENGLISH );
ZonedDateTime zdt = formatter.parse ( input , ZonedDateTime :: from );
Dump to console.
System.out.println ( "zdt : " + zdt );
When run.
zdt : 2009-06-18T20:56:02-04:00[America/New_York]
Adjust Time Zone
For fun let's adjust to the India time zone.
ZonedDateTime zdtKolkata = zdt.withZoneSameInstant ( ZoneId.of ( "Asia/Kolkata" ) );
zdtKolkata : 2009-06-19T06:26:02+05:30[Asia/Kolkata]
Convert to j.u.Date
If you really need a java.util.Date object for use with classes not yet updated to the java.time types, convert. Note that you are losing the assigned time zone, but have the same moment automatically adjusted to UTC.
java.util.Date date = java.util.Date.from( zdt.toInstant() );
How about getSelectedDate? Anyway, specifically on your code question, the problem is with this line:
new SimpleDateFormat("yyyy-MM-dd");
The string that goes in the constructor has to match the format of the date. The documentation for how to do that is here. Looks like you need something close to "EEE MMM d HH:mm:ss zzz yyyy"
In response to:
"How to convert Tue Sep 13 2016 00:00:00 GMT-0500 (Hora de verano central (México)) to dd-MM-yy in Java?", it was marked how duplicate
Try this:
With java.util.Date, java.text.SimpleDateFormat, it's a simple solution.
public static void main(String[] args) throws ParseException {
String fecha = "Tue Sep 13 2016 00:00:00 GMT-0500 (Hora de verano central (México))";
Date f = new Date(fecha);
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
sdf.setTimeZone(TimeZone.getTimeZone("-5GMT"));
fecha = sdf.format(f);
System.out.println(fecha);
}

Convert String To Date BRT

I'm trying convert a String to Date, but I haven't gotten it.
My String is in the format:
"Fri Jun 13 10:24:01 BRT 2014"
I have Googled and found this resolution, but still continue catching an Exception.
Here is my code:
java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("EEE MMM dd HH:mm:ss 'BRT' yyyy", Locale.getDefault());
df.setTimeZone(TimeZone.getTimeZone("BRT"));
try {
return df.parse(dateString);
} catch (Exception e) {
return null;
}
You need:
SimpleDateFormat df = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
df.setTimeZone(TimeZone.getTimeZone("BRT"));
DateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Date d = df.parse("Fri Jun 13 10:24:01 BRT 2014");
System.out.println(utcFormat.format(d)); // output: 2014-06-13T12:24:01+0200
Consider following corrections:
Locale.ENGLISH instead of Locale.getDefault() enables reliable parsing of english names like "Jun" or "Fri"
Use pattern symbol z instead of literal 'BRT' because else the parser cannot interprete the string "BRT" as an abbreviation of a timezone name that is interpreting as Brazil Standard Time (in your case just parsing as literal hence not taking in account the timezone offset of UTC-03:00).
The answer by Meno Hochschild is correct. Pay attention to those items (1) & (2).
Joda-Time
FYI, using Joda-Time or java.time (new package in Java 8) is recommended over the notoriously troublesome java.util.Date and .Calendar classes.
Example in Joda-Time 2.3.
String input = "Fri Jun 13 10:24:01 BRT 2014";
Via a Locale object, specify the language by which to interpret the day-of-week and month names during the parsing.
DateTimeFormatter formatter = DateTimeFormat.forPattern( "EEE MMM dd HH:mm:ss z yyyy" ).withLocale( Locale.ENGLISH );
Rather than rely on the default, specify a time zone to assign to the fresh DateTime object resulting from the parsing. Unlike a java.util.Date object, a DateTime truly knows its own assigned time zone.
DateTimeZone timeZone = DateTimeZone.forID( "America/Sao_Paulo" ); // Arbitrary choice of example time zone.
DateTime dateTime = formatter.withZone( timeZone ).parseDateTime( input );
Usually you should be working in Universal Time (UTC). Easy to convert.
DateTime dateTimeUtc = dateTime.withZone( DateTimeZone.UTC );
Built-in formatter is based on ISO 8601 format.
String output = dateTime.toString();
Or define your own pattern, or use one of the other pre-defined formats.
String outputInAwkwardFormat = formatter.print( dateTime );

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.

Why does this SimpleDataFormat parsing fail on Android?

DateFormat sdf = new SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy");
sdf.parse("Sun Dec 13 10:00:00 UTC 2009")
result
java.text.ParseException: Unparseable date: Sun Dec 13 10:00:00 UTC
2009
Note: This code seems to work in a normal Java application but seems to fail on Android.
It doesn't for me - perhaps your default locale uses different month names? Specify the locale for the format.
// Will definitely work
DateFormat sdf = new SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy",
Locale.US);
// Will definitely not work
DateFormat sdf = new SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy",
Locale.FRANCE);
// Might work - depends on default locale
DateFormat sdf = new SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy")
(The problem is the names of the days of the week and months of the year, which are obviously culture-specific. Date and time separators can vary too.)
EDIT: It's odd that you're still having problems. Just to check, please try to run the following short but complete program:
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Locale;
public class Test {
public static void main(String[] args) throws Exception {
DateFormat sdf = new SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy",
Locale.US);
sdf.parse("Sun Dec 13 10:00:00 UTC 2009");
}
}
If that doesn't work, try taking out the time zone part of both the pattern and the text. I wonder whether it's having problems with that.
EDIT: If the Android SimpleDateFormat implementation doesn't manage to parse the time zone, you can probably just use:
text = text.replace(" UTC ", " ");
Date parsed = sdf.parse(text);
... having set the time zone on the parser to UTC, of course. You probably want to check that it contains " UTC " first, just in case your data format changes.
Your format looks correct. Is it possible that you are not using an English Locale though? The formatter will take your system locale and this could result in different names for 'sun' and 'dec'

Categories

Resources