我有一个小时,分钟,日期和毫秒时间戳,我正在尝试创建一个表示时间的Date对象。时间戳在东部夏令时提供。
在解剖问题时,我创建了一些简单的测试代码,以查看发生的情况,并观察了以下内容:
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());
这会产生输出:
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
但是,如果我稍微改变一下代码:
boolean print = false;
我得到以下(不同)结果(!)
After setting time zone, time is: Mon Jan 06 23:00:00 EST 2014
有谁知道为什么会这样?
答案 0 :(得分:6)
如gtgaxiola所述:来自Calendar Documentation
在 Field Manipulation 部分下:
set(f,value)将日历字段f更改为值。此外,它设置内部成员变量以指示日历字段f已更改。虽然日历字段f立即更改,但在下一次调用get(),getTime(),getTimeInMillis(),add()或roll()之前,不会重新计算日历的时间值(以毫秒为单位)。
问题是您的getTime()
调用会重新计算日期,但setTimeZone(..)不会将内部成员变量isTimeSet
设置为false。所以你的第一个输出中的最后一行对你来说是错误的,因为你期望考虑时区而不是。
答案 1 :(得分:5)
在 Field Manipulation 部分下:
set(f,value)将日历字段f更改为值。此外,它设置内部成员变量以指示日历字段f已更改。虽然日历字段f立即更改,但在下一次调用get(),getTime(),getTimeInMillis(),add()或roll()之前,不会重新计算日历的时间值(以毫秒为单位)。
因此,对set()的多次调用不会触发多次不必要的计算。作为使用set()更改日历字段的结果,其他日历字段也可能会更改,具体取决于日历字段,日历字段值和日历系统。此外,在重新计算日历字段后,get(f)不一定返回通过调用set方法设置的值。具体情况由具体日历类确定。
答案 2 :(得分:5)
您需要先设置时区。请参阅下面的GregorianCalendar.setTimeZone的定义:
public void setTimeZone(TimeZone value)
{
zone = value;
sharedZone = false;
/* Recompute the fields from the time using the new zone. This also
* works if isTimeSet is false (after a call to set()). In that case
* the time will be computed from the fields using the new zone, then
* the fields will get recomputed from that. Consider the sequence of
* calls: cal.setTimeZone(EST); cal.set(HOUR, 1); cal.setTimeZone(PST).
* Is cal set to 1 o'clock EST or 1 o'clock PST? Answer: PST. More
* generally, a call to setTimeZone() affects calls to set() BEFORE AND
* AFTER it up to the next call to complete().
*/
areAllFieldsSet = areFieldsSet = false;
}
答案 3 :(得分:3)
我只想先设定时区:
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);
然而它正在做它应该做的事情,正如美国东部时间早上4点的评论所述。
甚至更好的解决方案是不来使用Calendar
,例如joda-time。
编辑:这为我提供了合适的时间。
Date today = new Date();
int hour = 4, min = 0, sec = 0, ms = 64;
boolean print = false;
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.setTimeZone(TimeZone.getTimeZone("EDT"));
if(print)
System.out.println("After setting time zone, 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());
System.out.println("TIME: "+cal.getTime());
答案 4 :(得分:1)
您在GMT中创建当前日期的实例:
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(today);
然后将时间更改为凌晨4点:
cal.set(Calendar.HOUR_OF_DAY,hour);
cal.set(Calendar.MINUTE,min);
cal.set(Calendar.SECOND,sec);
之后,您将日期从GMT转换为EST,即23 00:
cal.setTimeZone(TimeZone.getTimeZone("EDT"));
调试器将帮助您在每一步中看到这些更改:)