We have one of our application hosted on a application server installed on machine working in CST timings. Now in the application footer we are showing the Last Login time and date using java.util.date().toString();
Now from reference of this post I can say java.util.Date().toString() is using TimeZone.getDefault() method which, in turn, will default to the time zone of the operating system it is running on (i.e. the host).
So the application Should show the timings according to CST timzone but it is not happening only for this server, it is always showing GMT timzone.
Here is a attached screenshot showing time configuration and the results from ‘time’ command on the serve, as well as the application Admin UI, showing time in GMT which is visible in footer.
So I am looking for the possible causes as why java.util.date.toString() is showing this unexpected behavior and what is the solution for that?
As you have already recognized, the behaviour of java.util.Date.toString() is based on TimeZone.getDefault().
Use the user.timezone property value as the default time zone ID if it's available.
Detect the platform time zone ID. The source of the platform time zone and ID mapping may vary with implementation.
Use GMT as the last resort if the given or detected time zone ID is unknown.
The JVM might not be able to interprete the timezone of the underlying operating system, for example if the OS uses Windows timezone names which cannot be resolved to identifiers common in iana-tzdb.
Solution:
I suggest you to start the JVM with following system property:
-Duser.timezone=America/Chicago
Better use Joda-Time, a date-time object (DateTime) truly does know its assigned time zone. That means an offset from UTC and the rules and history of that time zone’s Daylight Saving Time (DST) and other such anomalies.
The standard date and time classes prior to Java SE 8 are poor. By tackling this problem head-on, Joda-Time became the de facto standard date and time library for Java prior to Java SE 8.
DateTimeZone dateTimeZone = DateTimeZone.forID("America/Chicago");
DateTime dateTime = DateTime.now(dateTimeZone);
System.out.println("Current time is: " + dateTime);
References:
Joda Time:
http://googleweblight.com/?lite_url=http://www.joda.org/joda-time/&ei=fiQH2-Y-&lc=en-IN&s=1&m=717&host=www.google.co.in&ts=1456818933&sig=ALL1Aj74vOgr-H7yxBKCAWq5KKQ28MTvvw
Time zones:
http://joda-time.sourceforge.net/timezones.html
A java.util.Date object represents a timestamp. A timestamp is a specific moment in time and has no concept of a timezone. When displaying a java.util.Date you need to format the time with respect to a given timezone.
The usual way to do this is using java.text.DateFormat:
Date d = new Date()
DateFormat dateForamt = DateFormat.getDateTimeInstance()
// The default timezone is the timezone that is default for the user, but it
// can be changed like so:
dateFormat.setTimeZone(someTimezone)
System.out.println(dateFormat.format(d))
Related
I support a large enterprise app and we have two classes that use LocalDate.now to get a timestamp, one uses joda time, one uses Java time. Typically we restart every night, but earlier this week we weren't able to. On the second day of the application running, the class using joda time returned the correct date (20200505) but the class using Java time returned the date the application was turned on (20200504).
Both classes make a new call to LocalDate.now in the method each time it's called.
Java time:
String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
//Use timestamp
Joda time:
LocalDate date = LocalDate.now();
String format1 = date.toString("MM/dd/yyyy");
//Use date
Why does the Java 8 implementation of LocalDate.now return the wrong date after the server date has changed without an application restart?
The class with the issue is an enum, and it turns out in another call the value of a field in the enum was being changed and saved, so when the app was doing the timestamp replacement, the placeholder was no longer in the enum after the first call. Who knows why. Fixing this fixed the issue, no problem with Java time.
The local date depends on the default time zone, as there is no global date.
I assume that the time zone in your server is off, and this still returns yesterday's date for a few hours after midnight. This is a quite common configuration error when configuring the server to run in UTC whilst the actual timezone is more on the eastern side.
https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html#getDefault--
If the cached default TimeZone is available, its clone is returned.
Otherwise, the method takes the following steps to determine the
default time zone.
Use the user.timezone property value as the default time zone ID if it's available.
Detect the platform time zone ID. The source of the platform time zone and ID mapping may vary with implementation.
Use GMT as the last resort if the given or detected time zone ID is unknown.
You can easily verify that by getting the LocalDate.now() after changing the default time zone:
TimeZone defaultTimeZone = TimeZone.getDefault();
try {
Arrays.stream(TimeZone.getAvailableIDs())
.map(TimeZone::getTimeZone)
.forEach(timeZone -> {
TimeZone.setDefault(timeZone);
System.out.printf("%s in %s (%s)\n",
LocalDate.now(), timeZone.getID(), timeZone.getDisplayName());
});
} finally {
TimeZone.setDefault(defaultTimeZone);
}
So the question is: which time zone does your server use?
I am trying to print the current system date and time as below,
public class PrintDate {
public void getDate(){
while(true){
System.out.println(new Date());
}
}
public static void main(String[] args) {
new PrintDate().getDate();
}
}
This endless loop prints the current system time stamp as expected and it works fine when i make change in date or time in the OS but not with the timezone change..
Example :
I started the above code , which continuously print the current system time stamp as expected.
When i change the system date or time , it successfully gets reflected in the code.
When i change the system timezone , It is not reflecting in the code. It still show the same timezone since the program started.
May i know the reason behind this?
The time zone is part of the environment of the process. Changing the time zone globally for your system only affects new processes.
See also How to set time zone of a java.util.Date?:
Be aware that java.util.Date objects do not contain any timezone
information by themselves - you cannot set the timezone on a Date
object. The only thing that a Date object contains is a number of
milliseconds since the "epoch" - 1 January 1970, 00:00:00 UTC.
As ZZ Coder shows, you set the timezone on the DateFormat object, to
tell it in which timezone you want to display the date and time.
The answer by neuhaus is correct.
If you meant you changed the time zone of your host operating system while running that code, know that the Java Virtual Machine (JVM) has its own current default time zone.
Usually that default is picked up from that of the host OS. If so in your case, that must mean your Java implementation is detecting the host time zone only at launch and not checking for later changes in the host OS‘ time zone.
The time zone of your JVM can also be set as a configuration parameter upon launch. In that case I should think the JVM would purposely ignore the host OS’ time zone changes.
Any Java code in any thread of any app within that JVM can change the JVM’s current default time zone at any moment during runtime. Again, I should think the JVM would purposely ignore the host OS’ time zone changes.
The class doc for java.util.TimeZone.getDefault() outlines steps taking in determining the current default time zone.
If the cached default TimeZone is available, its clone is returned. Otherwise, the method takes the following steps to determine the default time zone.
• Use the user.timezone property value as the default time zone ID if it's available.
• Detect the platform time zone ID. The source of the platform time zone and ID mapping may vary with implementation.
• Use GMT as the last resort if the given or detected time zone ID is unknown.
The default TimeZone created from the ID is cached, and its clone is returned. The user.timezone property value is set to the ID upon return.
In my reading of that, it says the JVM is not going to detect any changes to the host OS setting. Once launched, and once a default has been determined, it is stored in that user.timezone property (and a value in cache) until changed with a call to setDefault.
java.time
You are using the old java.util.Date class which has been supplanted by the java.time framework in Java 8.
Use the java.time.ZonedDateTime class and specify the desired/expected time zone.
ZoneId zoneId = ZoneId.of( " America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.now( ZoneId );
You should almost never depend on the JVM’s current default time zone ( nor the current default Locale).
import java.util.Date;
public class DateDemo {
public static void main(String args[]) {
//Instantiate a Date object
Date date = new Date();
//display time and date using toString()
System.out.println(date.toString());
}
}
We are storing time in like '22-NOV-17 05.33.51.937000000 PM' format with server default timezone CST. We have half an our time comparison in many places. So CST to CDT and CDT to CST are facing issues because on retrieval time for database we can not identify the time zone. So it is breaking our time comparison on CST to CDT and CDT to CST time changes.
We can not change our storing logic like store with timezone and store in UTC timezone because it will breaking our existing logic in many places.
So is there any way to identity date timezone like CST or CDT, stored in database with '22-NOV-17 05.33.51.937000000 PM' format.
We are storing time in like '22-NOV-17 05.33.51.937000000 PM' format
does not make sense with your comment
We are storing as a timestamp in database
In Oracle databases, a TIMESTAMP does not have a format - it is stored in the database as 11 bytes representing year (2 bytes), month, day, hours, minutes, seconds (1 byte each) and fractional seconds (4 bytes). It is only when whatever interface you are using (SQL/Plus, SQL Developer, Toad, Java, PHP, etc.) to talk to the database decides to show it to you, the user, that that interface will format it as a string (but the database will just keep it as bytes without any format).
Assuming you are using SQL/Plus or SQL Developer then you can find the default format using:
SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_TIMESTAMP_FORMAT';
And change the default format using:
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SSXFF9';
Or for TIMESTAMP WITH TIME ZONE
ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD HH24:MI:SSXFF9 TZR';
So is there any way to identity date timezone like CST or CDT, stored in database with '22-NOV-17 05.33.51.937000000 PM' format.
No, without any other meta-data that could identify the source of the timestamp and indicate which location it came from (i.e. is there another column that links to the user who entered the data that could be mapped to a physical location and so a time zone) then it is impossible to determine which time zone it is from.
You will either need to:
change your database column to TIMESTAMP WITH TIME ZONE and store the time zone; or
convert all the values to the same time zone when you are storing them.
I am assuming by CST and CDT you mean North American Central Standard Time and Central Daylight Time such as observed in Rainy River, Chicago and Mexico (the city) among other places. More on this ambiguity later.
For 99.977 % of all times it is fairly easy to know whether they are standard time or daylight saving time. Only times from the two hours around the transition from DST to standard time are ambiguous, and as said in the comments, there is no way to know from the time stamp which is the right way to resolve this ambiguity.
java.time
This answer will take you as far into the future as possible without taking you away from Java 7. You can still use java.time, the modern Java date and time API also known as JSR-310. It has been backported to Java 6 and 7 in the ThreeTen Backport, so it’s a matter of getting this and adding it to your project (just until one day you upgrade to Java 8 or later).
I am taking your word for your date-time string format. What we can do with it:
DateTimeFormatter storedFormatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("d-MMM-uu hh.mm.ss.SSSSSSSSS a")
.toFormatter(Locale.US);
ZoneId zone = ZoneId.of("America/Mexico_City");
String storedTime = "22-NOV-17 05.33.51.937000000 PM";
LocalDateTime dateTime = LocalDateTime.parse(storedTime, storedFormatter);
// First shot -- will usually be correct
ZonedDateTime firstShot = ZonedDateTime.of(dateTime, zone);
System.out.println(firstShot);
This prints:
2017-11-22T17:33:51.937-06:00[America/Mexico_City]
You can see that it picked an offset of -06:00, which means that the time is in standard time (CDT is -05:00).
Since your month abbreviation is in all uppercase, I needed to tell the formatter to parse case insensitively. If America/Mexico_City time zone is not appropriate for you, pick a better one, for example America/Rainy_River or America/Chicago.
Ambiguous times in fall
I once had to parse a log file containing date-times without indication of standard time and summer time (DST). Since we assumed time would always move forward, we failed at the transition to standard time, and one hour of the log file was lost. In this case we might have solved it using the information that times were in summer time until the leap backward by an hour, from there they were in standard time. You may want to think about whether something similar will be possible for you.
Other options include just taking DST time every time — this is what the above code will do — or taking an average and living with the error thus introduced.
We can at least detect the ambiguous times:
ZoneOffset standardOffset = ZoneOffset.ofHours(-6);
ZoneOffset dstOffset = ZoneOffset.ofHours(-5);
// check if in fall overlap
ZonedDateTime standardDateTime
= ZonedDateTime.ofLocal(dateTime, zone, standardOffset);
ZonedDateTime dstDateTime
= ZonedDateTime.ofLocal(dateTime, zone, dstOffset);
if (! standardDateTime.equals(dstDateTime)) {
System.out.println("Ambiguous, this could be in CST or CDT: " + dateTime);
}
Now if the string was 29-OCT-17 01.30.00.000000000 AM, I get the message
Ambiguous, this could be in CST or CDT: 2017-10-29T01:30
ZonedDateTime.ofLocal() will use the provided offset for resolving the ambiguity if it is a valid offset for the date-time and zone.
Non-existing times in the spring
Similarly we can detect if your date-time falls in the gap where the clock is moved forward in the transition to DST:
// Check if in spring gap
if (! firstShot.toLocalDateTime().equals(dateTime)) {
System.out.println("Not a valid date-time, in spring gap: " + dateTime);
}
This can give a message like
Not a valid date-time, in spring gap: 2018-04-01T02:01
I suggest you can safely reject such values. They cannot be correct.
Avoid the three letter time zone abbreviations
CST may refer to Central Standard Time (in North and Central America), Australian Central Standard Time, Cuba Standard Time and China Standard Time. CDT may mean Central Daylight Time or Cuba Daylight Time. The three and four letter abbreviations are not standardized and are very often ambiguous. Prefer time zone IDs in the region/city format, for example America/Winnipeg.
I have a Java program that runs on a linux virtual machine as a cron job. Currently there's an issue, the following line is used as part of logging to store the current date and time:
String date = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(new Date());
After daylight savings today, it was determined the system date was not set up correctly as it did not update. After fixing this using the following command, and restarting the linux environment the date is now correct and updated for daylight savings time.
ln -s /usr/share/zoneinfo/America/New_York /etc/localtime
However, when the Java program executes as part of the cron job, the date is still an hour behind. This causes timing issues internally as new Date() is used to get the current system time, which causes later problems in the process. For example at 5:00 PM, the Java program outputs 4:00 PM. Is there an additional consideration to this implementation? Shouldn't new Date() always return the current system date?
Adding debugging lines to the cron job, this executes with the expected correct time.
tl;dr
Instant.now()
Update your JVM’s tzdata
Work in UTC, especially your logging
Serialize to ISO 8601 formats
Date class
Shouldn't new Date() always return the current system date?
Yes, the Date class always captures the current moment in UTC. Let me repeat that: Date captures the moment in UTC.
The trouble comes from a well-intentioned but unfortunate “feature” of that class’ toString method where the JVM’s current default time zone is applied in generating that string. One of many reasons to avoid this outmoded and troublesome class.
I suspect that your “tzdata” time zone data file is outdated and not recognizing the new date for DST cutover.
Restart JVM
Java implementations typically pick up their current default time zone from the host OS when launching. After the JVM, changing the host OS’ time zone has no effect on the JVM.
Restart the JVM to pick up a new zone setting in host OS.
Use UTC on servers
Best practice is usually to set your servers to UTC. Then you do not need to worry about Daylight Saving Time nonsense.
Work in UTC
The bulk of your programming, logging, cron jobs, data exchange, and data serialization should be in UTC.
Note, for example, how Stack Overflow uses UTC in reporting your activity for "today" and "yesterday". Learn to think of UTC as The One True Time; all zones are a variation on that theme.
Apply a time zone only where critical, such as in presentation to a user expecting a certain zone.
Remember that your problem was not due to the bending of space-time. The seconds, minutes, and hours continued to increment normally, tick-tock tick-tock, in terms of UTC. Your problem was in the mistranslation into a time zone with outdated time zone rule change data.
Specify your desired zone in Java code
Your Java apps should always specify their desired/intended time zone explicitly. If omitted, the JVM’s current default time zone is implicitly applied.
That JVM default can be changed at any time by any code in any thread of any app within the JVM and immediately affect all other code in that JVM. So never depend on that current default for anything important. Confirm with the user, and specify explicitly in your code.
Avoid legacy date-time classes
The old date time classes including Date and Calendar are a bloody mess. Avoid them. They are now legacy, supplanted by the java.time classes.
Instant class is a moment on the time line with a resolution in nanoseconds, always in UTC.
Instant instant = Instant.now() ;
To generate a standard ISO 8601 formatted string, call toString. The Z on the end is short for Zulu and means UTC.
String output = instant.toString() ;
2017-01-23T12:34:56.123456789Z
Using those two simple lines of code would avoid your entire problem.
But you should be routinely updating the tzdata in:
host OS
JVM
Database system (Postgres, etc.)
Libraries such as Joda-Time
This seems like a stupid question, but I am not able to understand this creepy behavior. I am completely aware of the fact that java Date class does not store any TimeZone information in it. It just stores the number of milliseconds since January 1, 1970, 00:00:00 GMT
Thing is that, I am using MySql which is residing on a server with UTC timezone and I am also storing DateTime in UTC only. If I make a select query then I get this date 2014-01-17 16:15:49
By using http://www.epochconverter.com/ I get this:
Epoch timestamp: 1389975349
Timestamp in milliseconds: 1389975349000
Human time (GMT): Fri, 17 Jan 2014 16:15:49 GMT
Human time (your time zone): Friday, January 17, 2014 9:45:49 PM
Now comes the part of Hibernate. I am running my Java web app on a machine having IST as system timezone. I made a simple object fetch using Id and fetched createdDate property which is a Date object. I have wrote a simple code to understand its output, here is the code:
Date dt = c.getCreatedDate();
System.out.println(dt.getTime());
System.out.println(dt);
DateFormat df = new SimpleDateFormat("dd/MM/yyyy hh:mm a z");
df.setTimeZone(TimeZone.getTimeZone("IST"));
System.out.println(df.format(dt));
df.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(df.format(dt));
And following is the output for this:
1389955549000
2014-01-17 16:15:49.0
17/01/2014 04:15 PM IST
17/01/2014 10:45 AM UTC
If you put this 1389955549000 in http://www.epochconverter.com/ then you get following output:
GMT: Fri, 17 Jan 2014 10:45:49 GMT
Your time zone: Friday, January 17, 2014 4:15:49 PM GMT+5.5
This is not the expected output, right. It is giving me time in millis which is -5:30 from the UTC time, so If I try to get time in IST timezone then it actually gives me time which is in UTC
Does anyone got idea where I am doing wrong?
--------------------------How I fixed it----------------------------
Based on suggestions from - Ako and Basil Bourque
Hibernate takes system timezone into consideration while fetching date/time fields from database. If you have stored DateTime in UTC in database but your system time or for least your java app timezone is in other timezone(e.g, IST - Indian Standard Time) then hibernate thinks that DateTime stored in database is also in IST and this is what causes whole problem.
For this as Basil suggested, use same timezones accross different servers. UTC should be preferred. Fix that I applied is that I added following code:
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
in ServletContextListener which made my app timezone in UTC and now hibernate is fetching and storing dates as expected.
Confusing Question
Your question could use some rewriting.
If I make a select query – You should explain this and give the exact query statement.
Red Herring
Since dealing with two separate servers (database server, web app server), each with a different time zone setting, you should separate the question more cleanly. Indeed, the MySQL server seems to be just a red herring, a distraction.
Instead of talking about the irrelevant MySQL server, you should have tested and reported the actual time. Easy to do… Just google "current time in utc".
Thus the old sailors' adage: Use one compass or three, but never two.
Time Zones
Three-letter time zone codes are outmoded, being neither standardized nor unique. "IST" means "India Standard Time" and "Irish Standard Time", for example.
Use time zone names, as seen in this slightly outdated list. In your case, +05:30, you could use "Asia/Kolkata", also known as "Asia/Calcutta" in the older tables. That is 5.5 hours ahead of UTC/GMT.
Joda-Time
The java.util.Date & Calendar classes are notoriously bad and confusing, as you've come to see. Avoid them. Use either the open-source third-party Joda-Time or, in Java 8, the new java.time.* classes (inspired by Joda-Time).
The code below uses Joda-Time 2.3 and Java 8 on a Mac with US west coast time zone.
Baseline
Let's establish that 1389975349000L ≈ 16:15 UTC ≈ 21:45 India.
This agrees with EpochConverter.com, as the question stated.
// Specify a time zone rather than depend on defaults.
DateTimeZone timeZoneKolkata = DateTimeZone.forID( "Asia/Kolkata" );
long millis = 1389975349000L;
DateTime dateTimeUtc = new DateTime( millis, DateTimeZone.UTC );
DateTime dateTimeKolkata = dateTimeUtc.toDateTime( timeZoneKolkata );
Dump to console…
System.out.println( "millis: " + millis );
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "dateTimeKolkata: " + dateTimeKolkata );
When run…
millis: 1389975349000
dateTimeUtc: 2014-01-17T16:15:49.000Z
dateTimeKolkata: 2014-01-17T21:45:49.000+05:30
Mystery Number
The question mentions a second number: 1389955549000L.
That number turns out to be the same date as the first number, with different time.
Let's establish that 1389955549000L ≈ 10:45 UTC ≈ 16:15 India.
long mysteryMillis = 1389955549000L;
DateTime mysteryUtc = new DateTime( mysteryMillis, DateTimeZone.UTC );
DateTime mysteryKolkata = mysteryUtc.toDateTime( timeZoneKolkata );
Dump to console…
System.out.println( "mysteryMillis: " + mysteryMillis );
System.out.println( "mysteryUtc: " + mysteryUtc );
System.out.println( "mysteryKolkata: " + mysteryKolkata );
When run…
mysteryMillis: 1389955549000
mysteryUtc: 2014-01-17T10:45:49.000Z
mysteryKolkata: 2014-01-17T16:15:49.000+05:30
Conclusion
I'm not 100% sure, but…
→ Your web app server machine seems to have its clock set improperly, set to UTC time rather than India time.
The web app server is apparently let to 16:15 time in the India time zone, but apparently at that moment the true time in India was 21:45. In other words, the time did not match the time zone.
Mixing UTC time with non-UTC time zone = WRONG.
If you set an Indian time zone, then set an Indian time to match.
Details
Note that we have "16:15" in common in both sets of numbers.
The java.util.Date class has a very bad design where it has no time zone information itself BUT applies the Java Virtual Machine's default time zone in its implementation of toString. This is one of many reasons to avoid this class, but may be key to your problem.
Lessons Learned
Avoid java.util.Date, java.util.Calendar, and java.text.SimpleDateFormat classes. Use only as required for exchanging values as needed with other classes.
Use Joda-Time or the new java.time.* classes (JSR 310).
Specify a time zone, never rely on default time zone.
Match the time to time zone on each server. Verify by googling "current time in utc".
Set host server’s operating system’ time zone to UTC or GMT where possible. No such choice on some OSes, so choose "Atlantic/Reykjavik" as a workaround, because Iceland stays on UTC/GMT year-round without any Daylight Savings Time nonsense.
Do not set the JVM’s default time zone with a call to TimeZone.setDefault (except as a last resort in the worst situations). Setting the default is rude, as it immediately affects all the code in all the threads in all the apps running in that JVM. And it is unreliable as any of that other code can change it on your app, during runtime. Instead, specify a time zone in all your date-time code. Never rely implicitly on the JVM’s current default. Both Joda-Time and java.time have methods that take an argument of time zone. So, while it is a good practice to set all your server computers’ host OS’ time zone to UTC, you should never depend on that in your Java code.
There is another option of solving the time zone shift issue; in this case you don't have to put your entire JVM in the UTC time zone (it is not a good idea anyway; for example, you might want to share JVM across multiple Java applications and such a hacky solution can cause problems in the future).
So, there is a small open source project DbAssist, which provides a clean and elegant solution to this problem. Internally, it maps the java.util.Date fields in your entities to a custom UtcDateType. The custom type forces JDBC (and later Hibernate) to treat the dates in the database as UTC. There are different versions of this fix for different versions of Hibernate (its API was changed a couple of times between versions), so you have to pick a correct one according to the table here.
On the same page, you can also find the detailed instructions how to install and apply the fix. Generally, if you are using for example Hibernate 5.2.2, just add the following lines to your POM file:
<dependency>
<groupId>com.montrosesoftware</groupId>
<artifactId>DbAssist-5.2.2</artifactId>
<version>1.0-RELEASE</version>
</dependency>
Then, the application of the fix differs between JPA Annotations and HBM files setup, so I will present only example for one possible setup; for JPA Annotations case (without Spring Boot), just add this line to the persistence.xml file between <persistence-unit> tag:
<class>com.montrosesoftware.dbassist.types</class>
Now the dates in your entities are treated as UTC, when read/saved to the DB. If you want to learn more about the very essence of the date and timezone problem in Java/Hibernate, you can read this article explaining it with more details.