Showing posts with label date. Show all posts
Showing posts with label date. Show all posts

Tuesday, December 10, 2013

java.util.Date vs java.sql.Date

Congratulations, you've hit my favorite pet peeve with JDBC: Date class handling.
Basically databases usually support at least three forms of datetime fields which are date, time and timestamp. Each of these have a corresponding class in JDBC and each of them extendjava.util.Date. Quick semantics of each of these three are the following:
  • java.sql.Date corresponds to SQL DATE which means it stores years, months and days whilehour, minute, second and millisecond are ignored. Additionally sql.Date isn't tied to timezones.
  • java.sql.Time corresponds to SQL TIME and as should be obvious, only contains information about hour, minutes, seconds and milliseconds.
  • java.sql.Timestamp corresponds to SQL TIMESTAMP which is exact date to the nanosecond (note that util.Date only supports milliseconds!) with customizable precision.
One of the commonest bugs in JDBC drivers in relation to these three types is that the types are handled incorrectly. This means that sql.Date is timezone specific, sql.Time contains current year, month and day et cetera et cetera.

Finally: Which one to use?

Depends on the SQL type of the field, really. PreparedStatement has setters for all three values,#setDate() being the one for sql.Date#setTime() for sql.Time and #setTimestamp() forsql.Timestamp.
Do note that if you use ps.setObject(fieldIndex, utilDateObject); you can actually give a normal util.Date to most JDBC drivers which will happily devour it as if it was of the correct type but when you request the data afterwards, you may notice that you're actually missing stuff.

I'm really saying that none of the Dates should be used at all.

What I am saying that save the milliseconds/nanoseconds as plain longs and convert them to whatever objects you are using (obligatory joda-time plug). One hacky way which can be done is to store the date component as one long and time component as another, for example right now would be 20100221 and 154536123. These magic numbers can be used in SQL queries and will be portable from database to another and will let you avoid this part of JDBC/Java Date API:s entirely.

Monday, December 10, 2012

Java Calendar timezone converting to GMT problem

Just create a new Calendar in GMT, set the time in that calendar to the same as the original calendar, and you're done:
gmtCalendar.setTime(userCalendar.getTime());
That should be fine, as the getTime() call returns the instant in time (i.e. a java.util.Date with no associated time zone).
As ever though, if you're doing any significant amount of date/time work in Java you should strongly consider using Joda Time instead.

http://stackoverflow.com/questions/6790664/java-calendar-timezone-converting-to-gmt-problem

Friday, December 7, 2012

Time Zones and Daylight Saving Time in Java

You might think this would be simple but I actually spent a fair amount of time last week tracking down some confusing bugs. The problem is that the official documentation is pretty sparse and if you Google for support you will find many answers that are confused or flat-out wrong. Hopefully this will provide the straight dope.
The key Java classes are as follows:

java.util.TimeZone

This is an abstract class that contains the definition of a time zone, including that zone’s rules for Daylight Saving Time (or what Europeans refer to as “Summer Time.”) Any code that needs to explicitly deal with time zones should use a TimeZone object.
The best way to get a TimeZone is to call the static method TimeZone.getTimeZone() and pass it the standard “Olson name” such as “America/New_York” or “Pacific/Honolulu”.
This link lists all the standard time zone names.
You can call TimeZone.getTimeZone(“GMT”) or TimeZone.getTimeZone(“GMT-5″). None of these GMT-based TimeZone objects support Daylight Saving Time. (Note: “GMT” and “UTC” mean practically the same thing. GMT is defined in terms of astronomical observations and UTC is used for setting atomic clocks. For most practical purposes they can be treated as identical.)
You can also use common abbreviations e.g. TimeZone.getTimeZone(“EST”) instead of TimeZone.getTimeZone(“America/New_York”). This is strongly discouraged. Depending on circumstances you might get the wrong Daylight Saving Time behavior or even the totally wrong time zone, since the same 3-letter abbreviations are used around the world for different time zones.
When displaying a time zone to the user you should probably call TimeZone.getDisplayName(). Depending on the parameters you pass this will return a user-friendly value like “Eastern Standard Time”, “EST”, “Eastern Daylight Time” or “EDT”.

java.util.Calendar

This is an abstract class which serves as a wrapper around two independent values:
  • A time, stored as the number of milliseconds since January 1, 1970 00:000:00 GMT.
  • A TimeZone object which indicates how the time should be displayed.
(This is an oversimplification. The actual implementation is a a bit more complicated, but this is close enough as long as you are not actually digging into the source code.)
Note that the time offset is always supposed to be in GMT. If you see code samples that make a different assumption (and there are many out there on the web) ignore them.
Time zone conversions are simple: if you call setTimeZone() on a Calendar object you get the exact same time but displayed in the new time zone.
A more complex problem occurs when you get a time string from a user in a different time zone. If you parse the string “05-01-2012 08:35 AM” then the parser will generally give you a Calendar object for 8:35 AM in the computer’s default time zone.
If this is wrong then you will need to change the time offset to convert it to the correct time. If the time string was supposed to be in GMT then you can use the folowing code to convert it.

public static Calendar convertToGmt(Calendar c) {
    java.util.Date date = c.getTime();
    TimeZone tz = c.getTimeZone();
    long timeInMilliseconds = date.getTime();
    int offsetFromUTC = tz.getOffset(timeInMilliseconds);
    Calendar gmtCal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
    gmtCal.setTime(date);
    gmtCal.add(Calendar.MILLISECOND, offsetFromUTC);
    return gmtCal;
}

If it was supposed to be in a different time zone then you can call TimeZone.getOffset() for both time zones. The difference between the two values will give you the number of milliseconds that you need to add to do the conversion.
This code provides an alternate way to convert between arbitrary time zones.

public static Calendar convertToNewTimeZone(Calendar calendar, TimeZone timezone) {
    Calendar newCal = new GregorianCalendar(timezone);
    newCal.setLenient(false);
    boolean am = newCal.get(Calendar.AM_PM) == Calendar.AM;
    newCal.set(Calendar.YEAR, calendar.get(Calendar.YEAR));
    newCal.set(Calendar.MONTH, calendar.get(Calendar.MONTH));
    newCal.set(Calendar.DATE, calendar.get(Calendar.DATE));
    newCal.set(Calendar.HOUR, calendar.get(Calendar.HOUR));
    newCal.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE));
    newCal.set(Calendar.SECOND, calendar.get(Calendar.SECOND));
    newCal.set(Calendar.MILLISECOND, calendar.get(Calendar.MILLISECOND));
    boolean ampm = calendar.get(Calendar.AM_PM) == Calendar.PM;
    if (am && ampm) { // cal = 0 but we want 1
        newCal.roll(Calendar.AM_PM, 1);
    } else if (!am && !ampm) { //cal = 1 but we want 0
        newCal.roll(Calendar.AM_PM, -1);
    }
    return newCal;
}

Once again, this gives you a Calendar object with the same wall-clock time in a different time zone, as opposed to getting the same actual time in a different time zone.

ISO 8601

To avoid such problems when sending dates and times between different time zones you can use the ISO 8601 formats commonly used in XML documents. These formats allow an optional trailing time zone indicator e.g.
2012-05-01T08:35:01.123Z
2012-05-01T08:35:01.123-05:00
A “Z” code indicates that the time is GMT. A “-05:00″ indicates a time zone that is 5 hours behind GMT. In the U.S. this could mean either “Eastern Standard Time” or “Central Daylight Time”.
Most standard XML libraries can handle these formats.
In the “-05:00″ example above the parser will return a Calendar subclass whose TimeZone object is “GMT-5″, not “America/New_York” or “America/Chicago”. You have the correct time but you don’t really know which official time zone it is.
The time zone indicator is optional. If the document contains
2012-05-01T08:35:01.123
that will be interpreted as being in the receiving computer’s default time zone.

java.util.Date

This is a wrapper around a count of milliseconds since midnight January 1, 1970. There is no associated time zone.
According to the documentation the millisecond count should always be in GMT, but this is often ignored. You will find many code samples on the web that attempt to deal with time zones by adding or subtracting hours. This is NOT recommended.
If you need to deal with time zones you should use a Calendar object.
The Date class has methods like getHours() and getMinutes() which are all deprecated. If you use them they will return the value in the computer’s default time zone. Date.toString() will also display in the computer’s default time zone.

java.sql.Date

This is intended to represent a SQL DATE field. The Java implementation is a simple wrapper around java.util.Date which makes sure that the time part is always set to midnight in your computer’s default time zone.
What is actually stored in the database depends on the implementation but can be assumed to consist of a year, month and day in some format.

java.sql.Time

This is intended to represent a SQL TIME field. The Java implementation is a thin wrapper around java.util.Date which makes sure that the date part is always set to January 1, 1970.
What is actually stored in the database depends on the implementation but can be assumed to consist of either an offset from midnight or a combination of hour, minutes and seconds in some format.
There is no support for time zones built in. If time zones are important the application will have to keep track of them separately.

java.sql.TimeStamp

This intended to represent a SQL TIMESTAMP field. The Java implementation is similar to java.util.Date in that it contains an offset from a fixed starting time, but it is much higher precision, supporting fractions of a microsecond instead of milliseconds.
What is actually stored in the database depends on the implementation but is usually some sort of offset from a starting date.
TimeStamp is similar to java.util.Date in that
  • It does not contain a TimeZone.
  • The internal offset is supposed to be in GMT and bad things can happen if it is not.
  • It is typically displayed in the computer’s default time zone.
Usually you create a TimeStamp from a java.util.Date object. (If you are starting with a Calendar object just call getTime() on it.) So basically you are writing out the millisecond offset in the GMT time zone. If you started with a Calendar its original time zone is lost.
When you read a TimeStamp from the database you are getting back the time with no time zone information. Calling getDate() will return it as a java.util.Date object. If you want it in a time zone other than your computer’s default time zone you can do something like this:

Calendar cal = new GregorianCalendar(desiredTimeZone);
cal.setTime(ts.getDate);


http://bugfox.net/blog/2012/05/04/time-zones-and-daylight-saving-time-in-java/

Converting EST to EDT or vice versa in Java

How to retrieve TimeZone from java.util.Date instance?
There's no such thing. A Date just represents a number of milliseconds since the Unix epoch, which was midnight on January 1st 1970 UTC. It's not associated with a particular calendar system or time zone. To put it another way, if a friend and I are on the phone together (with a zero latency ;) and I click my fingers, we would both agree on the Date at which that click too place - even if I'm using the Gregorian calendar and he's using the Julian calendar, and even if I'm in London and he's in New York. It's the same instant in time.
How to know whether Daylight savings is applicable?, I suppose I can know it by doing timeZone.getDSTSavings, but problem I am facing is that even if I make my system's date as Feb 1 2012, still I am getting the value as positive (I guess 3600000)
Ideally, use Joda Time instead of java.util.Date/Calendar/TimeZone, but within TimeZone you can use TimeZone.getOffset(long) to find the offset from UTC, or TimeZone.inDaylightTime(Date) to just give you a yes/no answer.
How to convert EST time to EDT or vice versa?
Usually that's an invalid question - because at any one instance in time, either EST or EDT applies. You normally convert from one time zone to another, and "EDT" and "EST" aren't different time zones - they're different offsets within the same time zone. The fact that you're asking for this suggests that you may be modelling your data incorrectly to start with (which is unfortunately easy to do with date/time values). Please give us more information and we may be able to help you more.

http://stackoverflow.com/questions/9827139/converting-est-to-edt-or-vice-versa-in-java

Thursday, December 6, 2012

How can I get the current date and time in UTC or GMT in Java?

java.util.Date is always in UTC. What makes you think it's in local time? I suspect the problem is that you're displaying it via an instance of Calendar which uses the local timezone, or possibly using Date.toString() which also uses the local timezone.
If this isn't the problem, please post some sample code.
I would, however, recommend that you use Joda Time anyway, which offers a much clearer API.

http://stackoverflow.com/questions/308683/how-can-i-get-the-current-date-and-time-in-utc-or-gmt-in-java

Wednesday, December 5, 2012

Insert UTC date in Oracle database with Java and Spring

Neither java.util.Date nor Oracle Date stores timezone information. In your case Jdbc driver converts your date using the JVM timezone. You can use one of the following options:
  • If you are using PreparedStatement, you can use setDate(int parameterIndex, Date x, Calendar cal) method to specify Calendar in UTC timezone.
  • For Spring jdbcTemplate instead of inserting Date object, insert Calendar with UTC timezone
  • TimeZone.setDefault(TimeZone.getTimeZone("GMT")) could be set on JVM lvl
  • Use -Duser.timezone=GMT on JVM startup
http://stackoverflow.com/questions/12563553/insert-utc-date-in-oracle-database-with-java-and-spring

What is the default timezone in java.util.Date?

The date itself doesn't have any time zone. Its toString() method uses the current default time zone to return a String representing this date:
Date date = new Date();

System.out.println(TimeZone.getDefault());
System.out.println(date);

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

System.out.println(TimeZone.getDefault());
System.out.println(date);
Executing the above code on my machine leads to the following output:
sun.util.calendar.ZoneInfo[id="Europe/Paris",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=184,lastRule=java.util.SimpleTimeZone[id=Europe/Paris,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]]
Fri Jul 06 09:24:45 CEST 2012
sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
Fri Jul 06 07:24:45 UTC 2012
 
http://stackoverflow.com/questions/11337557/what-is-the-default-timezone-in-java-util-date