13

Got a strange weirdness when using Dates and Calendar. Point is I want to create a specific date e.g.

Calendar cal = Calendar.getInstance();
cal.set(1970, 0, 1, 0, 0, 0);
Date date = cal.getTime(); 

Now the thing is: it shows the correct date, but when debugging I see under the date-variable a "fasttime" of e.g. -3599459. This makes my JUnit tests fail, because the expected value is -3600000. It seems the Calendar adds 541 milliseconds or something like when initializing...

Question is: is it not possible to simply create a fixed date without this 'i'm adding some milliseconds in the background'-ghost function?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Malvin
  • 859
  • 2
  • 11
  • 19

6 Answers6

12

From the docs for the set method you're calling:

Sets the values for the fields YEAR, MONTH, DAY_OF_MONTH, HOUR, MINUTE, and SECOND. Previous values of other fields are retained. If this is not desired, call clear() first.

So it's retaining the millisecond value. It's not adding some milliseconds - it's taking the system time when you call getInstance, as it's documented to do.

Call clear() first, or explicitly set the millisecond value. (Personally I'd use clear(). I'd also explicitly set the time zone, just to make it clearer which time you're expecting.

Alternatively, use Joda Time to start with - it's a much more pleasant date/time API.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    @Malvin: Note that if you use `clear()`, that will be correct for the cases where you only set the year/month/day, or year/month/day/hour/minute... this is why I prefer using `clear()` over the answer you've accepted of *just* setting the milliseconds. – Jon Skeet Nov 13 '12 at 10:27
7

Add this line before calling cal.getTime():

cal.set(Calendar.MILLISECOND, 0);

This will make sure you set the milliseconds to zero.

Dan D.
  • 32,246
  • 5
  • 63
  • 79
0

A commonly used best practice is to introduce a Clock object to wrap all access to your Date/Time API.

Essentially, you have two implementations - a SystemTimeClock which forwards everything to your chosen Date/Time provider, and a mocked implementation to use for tests.

That way, your code becomes independent of specifics of the API and your tests run smoothly.

Urs Reupke
  • 6,791
  • 3
  • 35
  • 49
  • Joda Time has a similar feature for setting the system time virtually to a specific moment, which is useful for testing; see the methods in class `org.joda.time.DateTimeUtils`. – Jesper Nov 13 '12 at 09:17
  • Indeed. Turns out there was a similar question where Jon Skeet gave a similar answer to mine with a similar comment to yours...http://stackoverflow.com/questions/5622194/time-dependent-unit-tests – Urs Reupke Nov 13 '12 at 09:21
0

When working with dates, I'm pretty happy with the library Joda Time. I know it's not exactly an answer to your question, but maybe, it's worth looking into: http://joda-time.sourceforge.net/ JavaDocs: http://joda-time.sourceforge.net/apidocs/org/joda/time/DateTime.html

NickGreen
  • 1,742
  • 16
  • 36
0

The problem is that "set" does not set the "millisecond" value, so the millisecond value is still the value it had when you created the calendar with getInstance. You can call

cal.set(Calendar.MILLISECOND, 0);

before calling getTime, this will make sure that the milliseconds are 0. You can also directly create a gregorian calendar:

Calendar cal = new GregorianCalendar(1970, 0, 1, 0, 0, 0);
assertEquals(0, cal.get(Calendar.MILLISECOND));

If you want a more complete implementation of calendar and time functionality you can use Joda Time instead of the standard Java Calendar API.

David Tanzer
  • 2,732
  • 18
  • 30
-1
Calendar cal = Calendar.getInstance(); 
cal.setTime(new Date());
itzhar
  • 12,743
  • 6
  • 56
  • 63