Java - SimpleDateFormat wrong format - java

In my Postgresql database, I have a timestamp without time zone with this value : "2012-06-15 17:49:46.423" (default datatype used by Hibernate).
If I format with SimpleDateFormat and this pattern "EEEE dd MMMM yyyy", SimpleDateFormat#format returns "jeudi 14 juin 2012".
Why the result is not "vendredi 15 juin 2012" ?
French to English translation for non-french spoken :
"jeudi 14 juin 2012" => "Thursday 14th of June 2012"
"vendredi 15 juin 2012" => "Friday 15th of June 2012"
Hibernate 3.6.8.Final
JSF 2.0
JBoss 5.1.0.GA
Java 6
Thanks.

It's showing you just one day ahead of what you expect. Reason might be server time which is on another time zone I guess. Anyways the below code is working fine:
SimpleDateFormat sdf = new SimpleDateFormat("EEEE dd MMMM yyyy", Locale.FRENCH);
System.out.println(sdf.format(new Date()));

After searching, it turns out that I had two main options. Either I set the time zone through Hibernate or JSF.
Option 1 : Hibernate
I could change access type to Property. So in the setter, I would adjust the timestamp value to the right time zone. Another solution would be to create a custom Hibernate User Type.
Full details with code here : Mapping Dates and Time Zones with Hibernate, Part 2: Few Solutions
Option 2 : JSF
Last option, I either create a custom converter in JSF or more simply, I use the timeZone attribute of f:convertDateTime.
This how I did it :
<h:outputText value="#{row.date}">
<f:convertDateTime pattern="EEEE dd MMMM yyyy" locale="fr_FR" type="date" timeZone="Europe/Paris" />
</h:outputText>
All my dates are correct now !
Source (in french) : Comment utiliser le timezone du compensant JSF convertDateTime

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd MMMM yyyy zzzz G", Locale.FRENCH);
try this
also printing out a date will automatically print formatted date text in machine time zone.

Related

SimpleDateFormat parse

I have an issue with SimpleDateFormat:
Error:
Unparseable date: "Thu, 09 Nov 2017 16:17:42 GMT"
Code:
DF_SERVER_FORMAT="EEE, dd MMM yyyy HH:mm:ss'Z'"
....
var formater=SimpleDateFormat(DF_SERVER_FORMAT)
formater.parse(source)
as per SimpleDateFormat documentation, Z (capitalized) is for an RFC 822 time zone, e.g. -0800
for a General time zone use z.
this should work:
DF_SERVER_FORMAT="EEE, dd MMM yyyy HH:mm:ss z"
Try "EEE, d MMM yyyy HH:mm:ss z" this pattern works for me.
You can try to format some date using your pattern, to see the difference and then fix your pattern accordingly. Here is what I did in J2SE:
SimpleDateFormat df = new SimpleDateFormat("EEE dd MMM yyyy HH:mm:ss'Z'");
System.out.println(df.format(new Date()));
This is producing:
Thu 09 Nov 2017 17:49:07Z
But, when I used the pattern "EEE, dd MMM yyyy HH:mm:ss z", it produced the expected result:
Thu, 09 Nov 2017 17:51:09 CET
For anyone who either is fine with an external dependency (temporarily) or is using Java 8 or later I wanted to contribute the modern answer. Because I consider SimpleDateFormat long outdated.
The modern Java date and time API is generally much nicer to work with. In addition, your string is in RFC 1123 format, and the modern API comes with a formatter for this format. So no need to build your format pattern string yourself (my code is pure Java, I trust you to adopt to Kotlin):
String dateString = "Thu, 09 Nov 2017 16:17:42 GMT";
OffsetDateTime dateTime = OffsetDateTime.parse(dateString,
DateTimeFormatter.RFC_1123_DATE_TIME);
This produces an OffsetDateTime of 2017-11-09T16:17:42Z as expected.
To use this on Android, get ThreeTenABP, see this question: How to use ThreeTenABP in Android Project. Java 8 and later come with the modern API built-in. If using Java 6 or 7 on non-Android, you need the ThreeTen Backport.
What went wrong in your code? With your format pattern string you were asking for a literal Z right after the seconds, with no space in between. Since your input string didn’t have a Z there, parsing failed (instead it had a space and the offset ID GMT). In addition, your code seems to be sensitive to locale: if your default locale is one where the abbreviation for Thursday is not Thu or for November not Nov, parsing will fail (in contrast, RFC_1123_DATE_TIME expects (and requires) day and month abbreviations in English independently of locale).

Formatting date in Java

I am having a problem with formating a date using Java. The date formatter seems to parse my string using BST (British Summer Time) and not GMT+0 as defined by +0000 in the dateStr string in the code below.
String dateStr = "Tue Oct 02 01:06:00 +0000 2012";
DateFormat df = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");
Date date = df.parse(dateStr);
// Test the date
System.out.println(date.toString());
When I run the above code I get:
Tue Oct 02 02:06:00 BST 2012
Which is evidently not what I want. A useful point of information might be that when I run the following:
System.out.println(TimeZone.getDefault().getDisplayName());
I get:
Greenwich Mean Time
The output I'm trying to get is
Tue Oct 02 01:06:00 GMT 2012
I've already tried .setTimeZone on df but to no avail.
Note that Tue Oct 02 02:06:00 BST 2012 is the same time as Tue Oct 02 01:06:00 +0000 2012, just expressed in a different time zone. java.util.Date doesn't really deal with time zones, so as far as its concerned, there is no difference. The Date object you've constructed represents the correct date and time you want.
The Date.toString() method is essentially just a formatter that uses your JRE default TimeZone in its formatting. If you want to test that the Date object is correct, then you should build a java.util.Date object (using java.util.Calendar - most of the Date constructors have been deprecated) to test against. If you want to create a display string, then you should use the SimpleDateFormatter instance you've already created to format the Date object.
If you do need an object that stores TimeZone information, then you should use java.util.Calendar. java.util.Date is almost deprecated to the point of being unusable anyway. Or, do the same as I am and wait for the new Data and Time API coming out in Java 8.
The .toString() method is using your locale when printing the date.
Use:
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");
format.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(format.format(date));
I understand that BST is already deprecated in SE 7.
you can try like here:
DateFormat df = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy",
Locale.CANADA);
add Local args to SimpleDateFormat constructor

How to convert this "Tue Nov 13 14:35:04 +0000 2012" String format to date in Java?

How to convert the date Tue Nov 13 14:35:04 +0000 2012 String format to date in Java?
I know of Date.parse(String) but I don't know which format I should use for the date. Do I have to modify the string so that it can be parsed into date, and if yes then how?
Use SimpleDateFormat, with a format string of
"E MMM dd HH:mm:ss Z yyyy"
You should explicitly use Locale.US assuming these will definitely use English month/day names. (You don't want to be trying to parse French names just because the default locale is French, for example.)
Also, don't forget that the Date value returned will have no knowledge of the original time zone - it will have the right value for the instant represented in the original text, but don't expect the result of calling toString() to use the same zone - Date.toString() always uses the default time zone.
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.US);
Date test = sdf.parse("Tue Nov 13 14:35:04 +0000 2012");
System.out.print(test.toString());

Getting Date in HTTP format in Java

I'm trying to get a String of a date in Java in the format specified in HTTP 1.1. Which, as far as I can tell, is:
Fri, 31 Dec 1999 23:59:59 GMT
With the time always being GMT.
What would be the easiest way to get this from Date/Calendar/?
java.time
EDIT:
DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH).withZone(ZoneId.of("GMT"))
is the way to do it with pure java.time. HTTP 1.1 is to not a 100% match with RFC 1123, so using the java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME formatter will fail for day-of-month less than 10. (thanks to #PavanKamar and #ankon for pointing that out)
Note: to be backwards compliant, you would need to also support the other two formats specified by RFC 2616
In case someone else will try to find the answer here (like I did) here's what will do the trick:
String getServerTime() {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat dateFormat = new SimpleDateFormat(
"EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
return dateFormat.format(calendar.getTime());
}
in order to set the server to speak English and give time in GMT timezone.
If you're using Joda-Time (which I would highly recommend for any handling of dates and times in Java), you can do:
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
...
private static final DateTimeFormatter RFC1123_DATE_TIME_FORMATTER =
DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'")
.withZoneUTC().withLocale(Locale.US);
...
RFC1123_DATE_TIME_FORMATTER.print(new DateTime())
Two-digit day-of-month
Some applications require the format to include a two digit day-of-month as per RFC7231. The Java 8 DateTimeFormatter.RFC_1123_DATE_TIME uses a single digit:
System.out.println(DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now(ZoneOffset.UTC)));
Output: Wed, 1 Aug 2018 14:56:46 GMT
Some applications don't like that. Before you use the old answers that use Joda-time or a pre-java8 SimpleDateFormat, here's a working Java-8 DateTimeFormatter:
DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss O")
Now, when you do this:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss O");
System.out.println(formatter.format(ZonedDateTime.now(ZoneOffset.UTC)));
You get Wed, 01 Aug 2018 14:56:46 GMT - note the leading zero in the day-of-month field.
If you, like me, are trying to format a Java 8 java.time.Instant you need to explicitly add the time zone to the formatter. Like this:
Instant instant = Instant.now();
String formatted = DateTimeFormatter.RFC_1123_DATE_TIME
.withZone(ZoneOffset.UTC)
.format(instant);
System.out.println(formatted);
Which prints:
Tue, 15 Mar 2016 14:45:34 GMT
If you are not afraid of additional dependencies, you can use apache DateUtils:
import org.apache.http.impl.cookie.DateUtils;
DateUtils.formatDate(new Date(System.currentTimeMillis()));
// Tue, 17 Apr 2012 18:59:02 GMT
This will format your date with respect to RFC 822 RFC1123.
I know this is a late response but just wanted to add it for completeness.
You did not mention what you need the string for. But if you need it for an HTTP response header, you can use HttpServletResponse.setDateHeader(). It does all the formatting for you.
Calendar calendar = Calendar.getInstance();
SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
System.out.println("Date: " + dateFormat.format(calendar.getTime()));
You can play with it. The documentation is here:
http://download.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

TimeZone broken in SimpleDateFormat in android 2.3

Android 2.3 was recently released last night. So naturally I tried my app on it and found there was date formatting issue. I have noticed the DateFormatter produces different formats. So do this in a simple Java program:
((SimpleDateFormat)DateFormat.getDateTimeInstance(DateFormat.LONG,
DateFormat.LONG)).format(new Date());
Output is
December 7, 2010 11:49:40 AM EST
Do the same thing in an android emulator and you get
December 7, 2010 11:42:50 AM GMT-05:00
Notice the different time zone. Has anybody ran in to this issue? Is there another formatter I can use that doesn't depend on Java's implementation?
EDIT:
Ok so here is more detail to why I think this is broken:
Using this code:
private final DateFormat format =
new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
I tried to parse a date but the following error is thrown:
12-07 12:55:49.556: ERROR/DateDeserializer(847): Error when parsing date
java.text.ParseException: Unparseable date: "Mon, 06 Dec 2010 17:13:35 EST"
at java.text.DateFormat.parse(DateFormat.java:626)
at com.currency.mobile.client.DateDeserializer
.deserialize(DateDeserializer.java:31)
at com.currency.mobile.client.DateDeserializer
.deserialize(DateDeserializer.java:19)
at org.codehaus.jackson.map.deser.SettableBeanProperty
.deserialize(SettableBeanProperty.java:149)
There is nothing wrong with the output.
You create a DateFormat-Instance which depends on the default Locale. It is not unusual that on different machines, different java-installations the default Locale vary and so the output of locale-dependent operations. In this case the default TimeZone is different, but the two outputs in your question represent the same Date, printed with the same format String MMMMM d, yyyy hh:mm:ss a z.
UPDATE:
parse() in Android 2.3 will work with TimeZones like GMT+xxxx etc, but it doesn't recognize EST for example as a valid TimeZone for parsing. Android knows about EST if you use TimeZone.getTimeZone("EST").
UPDATE2:
Three-letter timezone IDs "EST", "HST", and "MST" are deprecated. Do not use them.
Both are same TimeZone just different representation
Looks like support for pattern "EEE MMM dd HH:mm:ss zzz yyyy" is also broken.
Evgueni

Categories