Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting values of Java Calendar does not give expected date-time

I have an hour, minute, date and millisecond timestamp, and am trying to create a Date object representing the time. The timestamp is provided in Eastern Daylight Time.

In dissecting the problem, I created some simple test code to see what was happening and have observed the following:

    Date today = new Date();
    int hour = 4, min  = 0, sec  = 0, ms   = 64;
    boolean print = true;

    Calendar cal = GregorianCalendar.getInstance();
    if(print)
        System.out.println("After initializing, time is: "+cal.getTime());
    cal.clear();
    if(print)
        System.out.println("After clearing, time is: "+cal.getTime());
    cal.setTime(today);
    if(print)
        System.out.println("After setting date, time is: "+cal.getTime());
    cal.set(Calendar.HOUR_OF_DAY,hour);
    if(print)
        System.out.println("After setting hour, time is: "+cal.getTime());
    cal.set(Calendar.MINUTE,min);
    if(print)
        System.out.println("After setting minute, time is: "+cal.getTime());
    cal.set(Calendar.SECOND,sec);
    if(print)
        System.out.println("After setting second, time is: "+cal.getTime());
    cal.set(Calendar.MILLISECOND,ms);
    if(print)
        System.out.println("After setting milliseconds, time is: "+cal.getTime());
    cal.setTimeZone(TimeZone.getTimeZone("EDT"));

    System.out.println("After setting time zone, time is: "+cal.getTime());

This produces the output:

After initializing, time is: Tue Jan 07 16:01:59 EST 2014
After clearing, time is: Thu Jan 01 00:00:00 EST 1970
After setting date, time is: Tue Jan 07 16:01:59 EST 2014
After setting hour, time is: Tue Jan 07 04:01:59 EST 2014
After setting minute, time is: Tue Jan 07 04:00:59 EST 2014
After setting second, time is: Tue Jan 07 04:00:00 EST 2014
After setting milliseconds, time is: Tue Jan 07 04:00:00 EST 2014
After setting time zone, time is: Tue Jan 07 04:00:00 EST 2014

However, if I change the code slightly:

boolean print = false;

I get the following (different) result (!)

After setting time zone, time is: Mon Jan 06 23:00:00 EST 2014

Does anyone know why this is happening?

like image 571
xirt Avatar asked Jan 07 '14 21:01

xirt


People also ask

How to set calendar’s time in Java?

The setTime(Date dt) method in Calendar class is used to set Calendars time represented by this Calendar’s time value, with the given or passed date as a parameter.

Why doesn't Java calendar show the date as 9/31/2014?

It doesn't work because you are setting the date to "09/31/2014" after your operations on calendar, and there is not day 31 in September 2014. By default, java Calendar is lenient, and will interpret that date as "10/01/2014" (1st October 2014). When a Calendar is in lenient mode, it accepts a wider range of calendar field values than it produces.

Why can't I see the time on a date in Java?

This is because the Date class in Java is a representation of a specific instant in time, expressed in milliseconds. Therefore, this makes it impossible to ignore the time on a Date. In the next sections, we'll show some common workarounds to tackle this problem. 2.1. Using Calendar

What is Settime () method of Java date class?

The setTime () method of Java Date class sets a date object. It sets date object to represent time milliseconds after January 1, 1970 00:00:00 GMT. Parameters: The function accepts a single parameter time which specifies the number of milliseconds.


2 Answers

As mentioned by gtgaxiola: From the Calendar Documentation

Under the Field Manipulation section:

set(f, value) changes calendar field f to value. In addition, it sets an internal member variable to indicate that calendar field f has been changed. Although calendar field f is changed immediately, the calendar's time value in milliseconds is not recomputed until the next call to get(), getTime(), getTimeInMillis(), add(), or roll() is made.

The problem is that your getTime() call recomputes the date but setTimeZone(..) doesn't set the internal member variable isTimeSet to false. So the last line in your first output is wrong for you because you expect the timezone to be considered which is not.

like image 167
fatih Avatar answered Sep 30 '22 05:09

fatih


From the Calendar Documentation

Under the Field Manipulation section:

set(f, value) changes calendar field f to value. In addition, it sets an internal member variable to indicate that calendar field f has been changed. Although calendar field f is changed immediately, the calendar's time value in milliseconds is not recomputed until the next call to get(), getTime(), getTimeInMillis(), add(), or roll() is made.

Thus, multiple calls to set() do not trigger multiple, unnecessary computations. As a result of changing a calendar field using set(), other calendar fields may also change, depending on the calendar field, the calendar field value, and the calendar system. In addition, get(f) will not necessarily return value set by the call to the set method after the calendar fields have been recomputed. The specifics are determined by the concrete calendar class.

like image 30
gtgaxiola Avatar answered Sep 30 '22 06:09

gtgaxiola