问题:您认为这是java.util.Calendar中的错误吗?
实例化本地(PDT)时区中的Calendar对象并为其指定零(纪元开始)日期。在将日历的毫秒,秒和分钟设置为零之后,按照预期保持该值。但是,一旦将一天中的小时设置为零,则时间变为非零。它 获取值-57600000ms = -16小时。这可能是时区错误,但是-16小时的值与执行时生效的本地-7小时(PDT)偏移不对应。没有夏令时,时间偏移为PST(-8小时),也不对应-16小时。
如果设置小时应该会影响时区偏移,那么您也可以设置分钟,因为:(来自https://en.wikipedia.org/wiki/Time_zone)有几个地方"使用与标准时间的半小时偏差,以及一些& #34; ......"使用四分之一小时的偏差。"
代码:
Date epochStart = new Date(0L);
System.out.println("epochStart=" + epochStart.getTime());
Calendar calendar = Calendar.getInstance();
calendar.setTime(epochStart);
System.out.println("epochStart in calendar=" + calendar.getTime().getTime());
calendar.set(Calendar.MILLISECOND, 0);
System.out.println("ms cleared in calendar=" + calendar.getTime().getTime());
calendar.set(Calendar.SECOND, 0);
System.out.println("second cleared in calendar=" + calendar.getTime().getTime());
calendar.set(Calendar.MINUTE, 0);
System.out.println("minute cleared in calendar=" + calendar.getTime().getTime());
calendar.set(Calendar.HOUR_OF_DAY, 0);
System.out.println("hourOfDay cleared in calendar=" + calendar.getTime().getTime());
输出:
epochStart=0
epochStart in calendar=0
ms cleared in calendar=0
second cleared in calendar=0
minute cleared in calendar=0
hourOfDay cleared in calendar=-57600000
我在java.util.Calendar中找到了其他bug的描述,但我不认为这是已知的。
- 谢谢你的时间。
答案 0 :(得分:1)
Java很好并按预期工作。
java.util.Date
是一个时刻,内部表示自纪元开始以来的毫秒(1970年1月1日00:00:00 UTC)。
java.util.Calender
用于以时区相关格式处理时间信息。通常,通过当前区域设置隐式定义时区。调用calendar.setTime(xxx)
会按时间提供所提供的时刻,并根据时区将其转换为日历字段(年,月,日,小时,分钟......)。
在您的情况下,纪元的开始分为Dec 31, 1969, 16:00:00.000 PDT
。清除毫秒,秒和分钟字段无效,因为这些字段已经为零。
但是,清除小时字段会将时间戳更改为
在您的情况下,时期的开始分为Dec 31, 1969, 00:00:00.000 PDT
。
以下代码显示了您的操作,以及将日历时间戳转换为UTC和PDT日期字符串。
import java.text.SimpleDateFormat;
import java.util.*;
public class CalendarTest {
public static void main(String[] args) {
TimeZone timeZone = TimeZone.getTimeZone("America/Los_Angeles");
SimpleDateFormat udf = new SimpleDateFormat("'UTC: 'yyyy-MM-dd HH:mm:ss.SSS Z");
udf.setTimeZone(TimeZone.getTimeZone("UTC"));
SimpleDateFormat df = new SimpleDateFormat("'PDT: 'yyyy-MM-dd HH:mm:ss.SSS Z");
df.setTimeZone(timeZone);
Date epochStart = new Date(0L);
System.out.println("epochStart=" + epochStart.getTime());
System.out.println(udf.format(epochStart));
System.out.println(df.format(epochStart));
System.out.println();
Calendar calendar = Calendar.getInstance(timeZone);
calendar.setTime(epochStart);
System.out.println("epochStart in calendar=" + calendar.getTime().getTime());
System.out.println(udf.format(calendar.getTime()));
System.out.println(df.format(calendar.getTime()));
System.out.println();
calendar.set(Calendar.MILLISECOND, 0);
System.out.println("ms cleared in calendar=" + calendar.getTime().getTime());
System.out.println(udf.format(calendar.getTime()));
System.out.println(df.format(calendar.getTime()));
System.out.println();
calendar.set(Calendar.SECOND, 0);
System.out.println("second cleared in calendar=" + calendar.getTime().getTime());
System.out.println(udf.format(calendar.getTime()));
System.out.println(df.format(calendar.getTime()));
System.out.println();
calendar.set(Calendar.MINUTE, 0);
System.out.println("minute cleared in calendar=" + calendar.getTime().getTime());
System.out.println(udf.format(calendar.getTime()));
System.out.println(df.format(calendar.getTime()));
System.out.println();
calendar.set(Calendar.HOUR_OF_DAY, 0);
System.out.println("hourOfDay cleared in calendar=" + calendar.getTime().getTime());
System.out.println(udf.format(calendar.getTime()));
System.out.println(df.format(calendar.getTime()));
System.out.println();
}
}
答案 1 :(得分:0)
LocalDate.now( ZoneId.of( "America/Montreal" ) )
.atStartOfDay( ZoneId.of( "America/Montreal" ) )
您正在使用现在由java.time类取代的麻烦的旧旧日期时间类。
似乎你正试图获得今天的第一时刻。不要假设并将时间硬编码为00:00:00
。在某些时区,由于夏令时(DST)等异常,日期可能会在不同的时间开始。让java.time确定第一时刻。
获取当前日期和时间。这需要一个时区。在任何特定时刻,日期和时间都会因全球区域而异。
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.now( z );
只提取日期,没有时间和没有时区。
LocalDate ld = zdt.toLocalDate();
要求当天的第一时刻,agsin甚至指定一个时区。
ZonedDateTime zdtStart = ld.atStartOfDay( z );