問題描述
在 Java 日期/日曆對像中發現神秘的毫秒數 (Mysterious milliseconds number found in Java Date/Calendar object)
Got a strange weirdness when using Date
s 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?
‑‑‑‑‑
參考解法
方法 1:
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.
方法 2:
Add this line before calling cal.getTime()
:
cal.set(Calendar.MILLISECOND, 0);
This will make sure you set the milliseconds to zero.
方法 3:
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.
方法 4:
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
方法 5:
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.
(by Malvin、Jon Skeet、Dan D.、Urs Reupke、NickGreen、David Tanzer)