在NetBeans中,我运行下面的代码。
一次运行的输出是
Intended time = 1970-0-1 0:0:0.000 GC time in ms = 102 Reformated GC time = 1970-01-01 00:00:00.102 Deprecated Date ms = 0 Deprecated time = 1970-01-01 00:00:00.000
另一次运行的输出是
Intended time = 1970-0-1 0:0:0.000 GC time in ms = 575 Reformated GC time = 1970-01-01 00:00:00.575 Deprecated Date ms = 0 Deprecated time = 1970-01-01 00:00:00.000
Q1:为什么重新格式化的时间(通过GregorianCalendar set(...)方法)具有额外的毫秒数-已过时-使用新的Date(...)不会!
Q2:为什么每次运行的毫秒数不同?
public class TestGregorianCalendar {
public static void main(String[] args){
String timeZoneString = "GMT+00";
GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone(timeZoneString));
int year = 1970;
int month = 0; // Jan
int day = 1;
int hour = 0;
int min = 0;
int sec = 0;
calendar.set(year, month, day, hour, min, sec);
long ms;
Date date;
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
df.setTimeZone(TimeZone.getTimeZone(timeZoneString));
System.out.println("Intended time = "+year+"-"+month+"-"+day
+" "+hour+":"+min+":"+sec+".000");
calendar.set(year, month, day, hour, min, sec);
ms = calendar.getTimeInMillis();
System.out.println("GC time in ms = "+Long.toString(ms));
date = new Date(ms);
System.out.println("Reformated GC time = "+df.format(date));
Date deprecatedDate = new Date(year-1900, month, day, hour+1, min, sec);
System.out.println("Deprecated Date ms = "+Long.toString(deprecatedDate.getTime()));
System.out.println("Deprecated time = "+df.format(deprecatedDate));
}
}
感谢您的见解!
答案 0 :(得分:2)
我建议您使用java.time(现代的Java日期和时间API)进行日期和时间工作。
OffsetDateTime dateTime = OffsetDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC);
System.out.println(dateTime);
long ms = dateTime.toInstant().toEpochMilli();
System.out.println(ms);
输出:
1970-01-01T00:00Z 0
没有多余的毫秒数,否则它们将被打印两次,每行输出一次。 java.time的数字与人类的月份相同,因此我将一月的数值设为1。OffsetDateTIme.of()
的参数列表中的最后0为纳秒,并确保秒的分数为0。>
如果要格式化输出:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS");
System.out.println(dateTime.format(formatter));
1970-01-01 00:00:00.000
评论中的Mark Rotteveel已经回答了您的两个问题。 new GregorianCalendar(TimeZone.getTimeZone(timeZoneString))
创建了一个GregorianCalendar
,代表毫秒在指定时区中的当前时刻。 calendar.set(year, month, day, hour, min, sec)
将上述字段设置为这些值。它不会更改其他字段,例如age和ms(秒)。因此,您获得的毫秒值反映了GregorianCalendar
对象创建的秒数,显然每次都不相同。这解释了明显的随机变化。这只是GregorianCalendar
众多令人困惑的方面之一。我建议您不要使用该课程。
new Date(year-1900, month, day, hour+1, min, sec)
–使用了自1997年2月起就被弃用的构造函数,因为它在各个时区中均不能可靠地工作–单独使用这些值创建了一个新的Date
对象,因此无需查看时钟,因此在这里毫秒是0。
Oracle tutorial: Date Time解释了如何使用java.time。
答案 1 :(得分:1)
Instant.EPOCH
Instant.EPOCH
是1970-01-01T00:00:00Z
时期的常量。
import java.time.Instant;
public class Main {
public static void main(String[] args) {
Instant instant = Instant.EPOCH;
System.out.println(instant);
}
}
输出:
1970-01-01T00:00:00Z
如果您需要一个表示该瞬间的日期时间字符串为不同的模式,则可以使用Instant#atOffset
将其转换为OffsetDateTime
,然后使用DateTimeFormatter
将其格式化为{所需的模式。
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
Instant instant = Instant.EPOCH;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS");
String formatted = formatter.format(instant.atOffset(ZoneOffset.UTC));
System.out.println(formatted);
}
}
输出:
1970-01-01 00:00:00.000
java.util
的日期时间API及其格式设置SimpleDateFormat
已过时且容易出错。我建议您应该完全停止使用它们,并切换到modern date-time API。在 Trail: Date Time 上了解有关现代日期时间API的更多信息。