Question

I have a timestamp that I am trying to put into a Date object, however when I use Calendar, I am running into a strange problem. I seem to be able to unable to create a Date object with the values I want:

public static void main(String args[]){
    Date today = new Date();
    int hour = 4, min=0, sec=0, ms=64;

    Calendar cal = GregorianCalendar.getInstance();

    cal.clear();
    cal.setTimeZone(TimeZone.getTimeZone("EDT"));
    cal.setTime(today);
    cal.set(Calendar.HOUR_OF_DAY,hour);
    cal.set(Calendar.MINUTE,min);
    cal.set(Calendar.SECOND,sec);
    cal.set(Calendar.MILLISECOND,ms);

    System.out.println("Time is: "+cal.getTime());
}

This produces:

Time is: Mon Jan 13 23:00:00 EST 2014

which is not the result I am looking for.

However, if I comment out the 'setTimeZone' method call, I get the following result:

Time is: Tue Jan 14 04:00:00 EST 2014

This is the result that I am looking for but I am concerned that if I am running on a machine that is not running in the same time zone, I will not get consistent behavior.

Was it helpful?

Solution 2

The problem here is that Java does not know of the timezone "EDT" (Eastern Daylight Time). As a result, Calendar seems to be setting the timezone to GMT.

The timezone needed here is "America/New_York" or "EST5EDT". When either of these values are used, the correct result is produced.

The list of valid Time Zones can be obtained by calling TimeZone.getAvailableIDs()

It is unfortunate that no warnings are produced when the requested Time Zone is not found.

OTHER TIPS

This is the result that I am looking for but I am concerned that if I am running on a machine that is not running in the same time zone

it is the problem. The internal representation should be ok, but it prints on local timezone: representation differs from real content.

use SimpleDateFormat http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html and set TimeZone to see the date on the Zone desired.

If you can do away with java.util.Date, you can use joda time API to conveniently set these values as desired:

For your query, you can set your already created Calendar instance as a constructor parameter to DateTime.

DateTime dt = new DateTime(cal);
System.out.println(dt.toDateTimeISO());

Output:

2014-01-14T04:00:00.064-05:00

Calendar.getTime() returns a java.util.Date object. Date objects do not know anything about timezones. The Date object that Calendar.getTime() returns does not know to what timezone the Calendar that it came from is set.

When you print a Date object (for example, by implicitly calling toString() object, as you are doing) it is formatted in the default time zone of the machine you are running it on.

If you want to print a Date in a specific timezone, use a SimpleDateFormat, and set the desired timezone on the SimpleDateFormat object. For example:

DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
df.setTimeZone(TimeZone.getTimeZone("EDT"));

// Will display the date that the calendar is set to in the EDT timezone
System.out.println(df.format(cal.getTime()));

Java Date objects represent the number of milliseconds seconds since January 1, 1970, 00:00:00 GMT due to the fact that the other methods are deprecated. The two ways to "view" a Date object directly are "getTime()" and "toString()" (using "dow mon dd hh:mm:ss zzz yyyy"). Therefore, you are formatting the GMT value to your local timezone.

When working with dates, it is best to think of them as GMT values, and then as a "formatting" exercise when viewing the date.

For comparison, here is that same kind of code but using Joda-Time 2.3.

Avoid the java.util.Date & .Calendar classes.

Never use three-letter codes for time zones. They are neither standardized nor unique. Instead use proper time zone names. In this case, use "America/New_York" or "America/Montreal".

// Use time zone names, such as from this slightly outdated list: http://joda-time.sourceforge.net/timezones.html
DateTimeZone timeZone = DateTimeZone.forID( "America/New_York" );

// Input.
int hour = 4, min = 0, sec = 0, ms = 64;

// Start with now, then adjust the time of day.
DateTime now = new DateTime( timeZone );
DateTime dateTime = now.withHourOfDay( hour ).withMinuteOfHour( min ).withSecondOfMinute( sec ).withMillisOfSecond( ms );

// If needed, translate to a java.util.Date for use with other classes.
java.util.Date date = dateTime.toDate();

Dump to console…

System.out.println( "now: " + now );
System.out.println( "dateTime: " + dateTime );
System.out.println( "date: " + date );

When run…

now: 2014-01-20T21:04:51.237-05:00
dateTime: 2014-01-20T04:00:00.064-05:00
date: Mon Jan 20 01:00:00 PST 2014
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top