My app is calling up a Twitter feed and a blog feed, both contain a post date of course. When my phone is set to English locale it works, when I switch to Dutch or German it fails. The code in question does not even call upon the locale, and the input values are also independent of the locale.
The offending code:
tweets is a JSONObject containing the complete Twitter feed.
final SimpleDateFormat formatter =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
final SimpleDateFormat parser =
new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");
for (int i = 0; i < tweets.length(); i++) {
final JSONObject tweet = tweets.getJSONObject(i);
// The following line is where the failure occurs:
values.put(KEY_TWEET_DATE, formatter.format(parser.parse(tweet
.getString("created_at"))));
}
This works as long as my locale is English.
As soon as I switch to German or Dutch (my app contains translations for those two languages, I haven't tried any other so far) I get an error like this:
WARN/System.err(28273): java.text.ParseException: Unparseable date: Wed Jun 29 10:55:41 +0000 2011
WARN/System.err(28273): at java.text.DateFormat.parse(DateFormat.java:645)
WARN/System.err(28273): at squirrel.DeaddropDroid.DeaddropDB.updateTwitter(DeaddropDB.java:1453)
The "unparseable date" is the correct date, in the expected format. My format string is designed to parse that exact date. And as said, when I switch my phone to English locale, it works just fine. It's the same code: the error occurs even when I switch the locale while the app is running, and disappears when I switch back the locale.
If you need to parse in a particular locale, pass that into the SimpleDateFormat constructor:
final SimpleDateFormat parser =
new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.US);
That means it will always use the US locale for day and month names etc.
Have you tried:
SimpleDateFormat parser =
new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy",Locale.getDefault());
Related
I am trying to convert date string from one format to another using SimpleDateFormat.
Conversion works but there is a dot "." after month.
String dateStr = "04/02/1987";
DateFormat df1 = new SimpleDateFormat("dd/MM/yyyy");
Date d = df1.parse(dateStr);
DateFormat df2 = new SimpleDateFormat("dd MMM yyyy");
System.out.println(df2.format(d));
Output is 04 Feb. 1987 instead of 04 Feb 1987.
What is your Locale.getDefault()?
Different output for alphanumeric date parts may be caused by the Locale the formatter is using. In most cases, the system default Locale is used if you don't specify one yourself. I don't know for sure SimpleDateFormat does so, but it seems likely.
I know that a java.time.format.DateTimeFormatter does so, see the following example which uses java.time, the modern and recommended to use datetime API:
public static void main(String[] args) {
String dateStr = "04/02/1987";
LocalDate localDate = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("dd/MM/yyyy"));
System.out.println(localDate.format(DateTimeFormatter.ofPattern("dd MMM yyyy",
Locale.ENGLISH)));
System.out.println(localDate.format(DateTimeFormatter.ofPattern("dd MMM yyyy",
Locale.FRENCH)));
}
Output:
04 Feb 1987
04 févr. 1987
The output is (of course) different concerning the name of the month, but using Locale.FRENCH shows a dot after the abbreviated month name. It is possible that your system's default Locale is one that indicates an abbreviation by a dot, too, but is identical to the output format of a Locale.ENGLISH for the numeric parts and the abbreviation of the month.
Please provide Locale.ENGLISH in SimpleDateFormat constructor while creating object as shown below:
String dateStr = "04/02/1987";
DateFormat df1 = new SimpleDateFormat("dd/MM/yyyy");
Date d = df1.parse(dateStr);
DateFormat df2 = new SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH);
System.out.println(df2.format(d));
My ideal way, of having a locale independent date string, is by using the following code
DateFormat dateFormat = new SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH);
which means, if I run the above code in a Arabic device, or a United States device, both will generate same string.
For the above case, dateFormat.format(date) will produce Dec 26, 2015.
I came across a legacy code, which is using the following way to generate locale independent date string.
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.ENGLISH);
Will the above code be truly locale independent. Will it "mistakenly" generate string like 26 Dec, 2015?
I wrote a simple code, to test both on Windows and Android device.
for (Locale locale : Locale.getAvailableLocales()) {
Locale.setDefault(locale);
DateFormat dateFormat0 = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.ENGLISH);
DateFormat dateFormat1 = new SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH);
if (false == dateFormat0.format(date).equals(dateFormat1.format(date))) {
throw new java.lang.RuntimeException("Opps");
}
}
No exception was being thrown.
I was wondering, can we assume that DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.ENGLISH) will generate same date string too across different devices? Is there any edge case I didn't handle?
Using "MMM dd, yyyy"you retain control of the output, where by using the integer constant DateFormat.DEFAULT you are leaving it up to the locale definitions for the platform. They should be identical across these platforms for any given locale, but there really are no guarantee.
The DateFormat.DEFAULT parameter is only useful if you work with different Locales, as it'll allow DateFormat to create the proper localized date string.
Example:
DateFormat dfEn = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.ENGLISH);
DateFormat dfFr = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.FRENCH);
DateFormat dfGe = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.GERMAN);
System.out.println("ENGLISH: " + dfEn.format(date));
System.out.println("FRENCH : " + dfFr.format(date));
System.out.println("GERMAN : " + dfGe.format(date));
prints:
ENGLISH: Dec 26, 2015
FRENCH : 26 déc. 2015
GERMAN : 26.12.2015
I you want to be sure that the rendered date looks always the same it's the best choice to define the format explicitely as you did in your first code snippet:
DateFormat dateFormat = new SimpleDateFormat("MMM dd, yyyy", Locale.ENGLISH);
The given locale here does not define the formatting but the wording to be used, here the name of the month is in english ("Dec"), rather than e.g. in german ("Dez").
I am developing a Web application into GWT and I am using the Object DatePicker. This object retrieves the date in a defined format which I am translating into a String such as:
Wed May 14 2014 00:00
For me it is useful to use this date as String for some operations. However, for one of them I need the Timestamp object. For that reason, I am making use of the SimpleDateFormat object in the following way:
SimpleDateFormat sdf = new SimpleDateFormat("E MMM dd yyyy HH:mm");
Timestamp tDateIni = new Timestamp(sdf.parse(sDateIni).getTime());
Yet, when I run the remote debug I get a ParseException. Do you know what could the mistake be? I think I am using in a bad format the SimpleDateFormat object in the part "E MMM", but I am not sure. Thanks a lot in advance!
If you want to parse the date at client side in GWT then try with DateTimeFormat
DateTimeFormat dateTimeFormat=DateTimeFormat.getFormat("E MMM dd yyyy HH:mm");
Date date=dateTimeFormat.parse("Wed May 14 2014 00:00");
If you want to parse the date at server side then pass the time in milliseconds as long value instead of date string from client side and form the date back at server side using new Date(timeInMills)
Your date format uses the day of the week format that requires "EEE" instead of "E". This is causing the exception when the program is trying to read in your date string. It is expecting one letter for the day of the week.
http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
Change this from
SimpleDateFormat sdf = new SimpleDateFormat("E MMM dd yyyy HH:mm");
to
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd yyyy HH:mm");
It should be EEE instead of E to represent Weekdays like Wed
Below code, perfectly works (TESTED)
public static void main(String[] args) {
String s = "Wed May 14 2014 00:00";
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd yyyy HH:mm");
try {
Timestamp tDateIni = new Timestamp(sdf.parse(s).getTime());
System.out.println(tDateIni.getTime());
} catch (ParseException ex) {
System.out.println("Parse Error");
}
}
I have added the Locale object in the SimpleDateFormat object and now it works. Thank you for all your help and your comments!!!
I'm fairly new here. I'm used to working with C# but I'm a newbie in java.
I'm trying to get an hour String out of a jSpinner (Date model), but I keep getting errors. I've looked into some answers that are already given here... but it still doesn't work.
uurStr returns "Sat Jan 25 16:09:49 CET 2014", I'm trying to get "16:09" out of it. But no luck so far.... any ideas?
The exception is thrown on the "uurDate = sdf.parse(uurStr);" part.
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
SimpleDateFormat outputFmt = new SimpleDateFormat("HH:mm");
String uurStr = String.valueOf(jSpinner1.getValue());
Date uurDate = null;
try {
uurDate = sdf.parse(uurStr);
} catch (ParseException ex) {
Logger.getLogger(frmBackEnd.class.getName()).log(Level.SEVERE, null, ex);
}
String uur = outputFmt.format(uurDate);
JOptionPane.showMessageDialog(null, uur);
In order to correctly parse the weekday and timezone information, which both are language specific, it is necessary to set the locale as follows:
final SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.US);
If the locale is not set, then the default locale of the JRE is taken. This may be the OS default locale or a user specific locale or the locale may have been overridden by another Java class with Locale.setDefault(Locale.XXXX). In any of these cases, this may be the correct locale or not.
That said, it is usually safer to set the timezone or you may get wrong time information if the timezone is not available in the string to be parsed:
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
In your example the timezone is available and you don't have to worry about that.
We have
One server A running on Jboss EAP6/Windows/US
Another server B running on Jboss EAP6/Linux/South America
Current spring application, has a UI page that pass a Date select box, when click submit, this date object will pass to the next page as a field of a java bean.
Now the situation is:
Server A runs this form fine without problem, but server B throw exception when submit:
nested exception is java.lang.IllegalArgumentException:
Unparseable string: [Unparseable date: "Wed May 29 16:34:58 ART 2013",
Unparseable date: "Wed May 29 16:34:58 ART 2013"]]
Seems server B doesn't know how to process the data format as Wed May 29 16:34:58 ART 2013, even I add an #initBinder
#InitBinder
public void registerDateBinder(WebDataBinder binder) {
DateFormat printFormat = new SimpleDateFormat(DateTimeFormat.patternForStyle("S-", LocaleContextHolder.getLocale())); // format for joda time dojo UI
printFormat.setLenient(false);
DateFormat sortFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy" , LocaleContextHolder.getLocale()); // format for whatever return from form
sortFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new ExpandableCustomDateEditor(printFormat, Arrays.asList(printFormat, sortFormat), true));
}
ExpandableCustomDateEditor is referred from this article
Interesting part is above issue happens when that Date object is a field of the bean
public String showSecondView(Form aForm,
Model uiModel) {
.....
}
But this works without problem in another controller without #InitBinder
public String list(Model uiModel,
#RequestParam(value = "fromDate", required = false) Date fromrDate,
.....)
....
}
But how come this error still happens, even with that #initBinder? I have made post before and seems platform has different way to translate timezone code, but Spring, I think it is capable to support internationalization right?
Nailed it.
The issue is mainly because of String to Date conversion, it is either
the format defined in DateFormat object does not match date String value, or
Current server environment cannot identify the timezone code or other time format by its current locale
So
solution to issue1: find the correct Date format, google is best friend
solution to issue2: remove locale from current `DateFormat` object, only use
DateFormat df = new DateFormat(String pattern);
instead of
DateFormat df = new DateFormat(String pattern, Locale aLocale);
when convert String to Date from what return from form
In my case, as we are on Spring framework so the reason of the problem is:
I did not quite 100% follow the post so
#InitBinder
public void registerDateBinder(WebDataBinder binder) {
DateFormat printFormat = new SimpleDateFormat(DateTimeFormat.patternForStyle("S-", LocaleContextHolder.getLocale())); // format for joda time dojo UI
printFormat.setLenient(false);
DateFormat sortFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy" , LocaleContextHolder.getLocale()); // NO LOCALE PlEASE!!!!!!
sortFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new ExpandableCustomDateEditor(printFormat, Arrays.asList(printFormat, sortFormat), true));
}
the problem is here
DateFormat sortFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy"); // AFTER REMOVE LOCALE
I remove the LocaleContextHolder.getLocale() from sortFormat initiation then it works like a charm. It seems we have to get rid of System local to convert the date String when the form return date string back from UI to the controller.
The reason it is ok is because the printFormat already take care of locale when put date information to UI
DateFormat printFormat = new SimpleDateFormat(DateTimeFormat.patternForStyle("S-", LocaleContextHolder.getLocale())); // format for joda time dojo UI
so once the Date string get back from the UI, it is not necessary to process with locale any fore and it should be ok we take out the locale for sortFormat. That's what I guess.
Cheers.