java.util.Date使用相同的输入参数显示不同的值
我尝试System.out相同的字符串
System.out.println(" DATE 29 " + new Date(1330462800000l) + " Date 01 "
+ new Date(1330549200000l));
但是当我在Build(在控制台模式下运行)中检查它时以及在Eclipse中运行应用程序时,我得到了不同的结果。
来自eclipse的输出(看起来像是正确的结果):
日期29 Wed Feb 29 00:00:00 EET 2012日期01 Thu Mar 01 00:00:00 EET 2012
从构建输出(控制台模式)
日期29 2月28日23:00:00 EET 2012日期01 Wed 2月29日23:00:00 EET 2012
对不起,愚蠢的问题,但你有任何想法可能的原因?
PS:我使用maven + tycho来构建包装类型的eclipse-repository(如果它真的很重要)
编辑:在Eclipse中,我看着timeZone值:
Calendar calendar=Calendar.getInstance();
System.out.println("!!!time zone before: " + calendar.getTimeZone());
!!!之前的时区:sun.util.calendar.ZoneInfo [id =“Europe / Minsk”,offset = 7200000,dstSavings = 3600000,useDaylight = true,transitions = 121,lastRule = java.util.SimpleTimeZone [id = Europe /明斯克,偏移= 7200000,dstSavings = 3600000,useDaylight =真,startYear = 0,STARTMODE = 2,startMonth = 2,朝九特派= -1,startDayOfWeek = 1,开始时间= 7200000,startTimeMode = 1,endMode = 2,endMonth = 9,endday指定= -1,一个endDayOfWeek = 1,结束时间= 7200000,endTimeMode = 1]]
然后我设置硬编码zoneId的时区并进行构建
calendar.setTimeZone(TimeZone.getTimeZone("Europe/Minsk"));
没有任何结果
编辑:我使用jres的不同版本和体系结构在build和eclipse中。它可能是原因吗? 编辑:
System.out.println("!!!!!! system.timezone " + System.getProperty("user.timezone"));
System.setProperty("user.timezone", "Europe/Minsk");
System.out.println("!!!!!! system.timezone " + System.getProperty("user.timezone"));
!!!!!! system.timezone欧洲/明斯克
!!!!!! system.timezone Europe / Minsk !!!区域后的日历时间:sun.util.calendar.ZoneInfo [id =“Europe / Minsk”,offset = 7200000,dstSavings = 3600000,useDaylight = true,transitions = 121,lastRule = java。 util.SimpleTimeZone [ID =欧洲/明斯克,偏移= 7200000,dstSavings = 3600000,useDaylight =真,startYear = 0,STARTMODE = 2,startMonth = 2,朝九特派= -1,startDayOfWeek = 1,开始时间= 7200000,startTimeMode = 1 ,endMode = 2,endMonth = 9,endday指定= -1,一个endDayOfWeek = 1,结束时间= 7200000,endTimeMode = 1]]
正确的时区。 但日期仍然是错误的
添加到测试:
System.out.println(Calendar.getInstance().getTimeZone());
要么
System.getProperty("user.timezone");
Java时区可以通过系统属性user.timezone设置,详情请参阅Java系统属性。
时间使用乔达时间。 您可以为所有乔达物体重新定义时区:
DateTimeZone.setDefault(DateTimeZone.UTC);
TL;博士
Instant.ofEpochMilli( 1_330_462_800_000L ) // Convert count-of-milliseconds-since-epoch to an `Instant`, a moment on the timeline in UTC.
.atZone( ZoneId.of( "Europe/Minsk" ) ) // Adjust into another time zone. Same moment, different wall-clock time.
避免遗留的日期时间类
您正在使用现在已经存在的麻烦的旧日期时间类,并被java.time类取代。 其中许多缺陷是Date::toString
方法在生成字符串时动态应用JVM的当前默认时区。 Date
代表UTC中的一个时刻,但这种善意的反特征带来了混乱。 JVM的当前默认时区可以随时更改,即使在运行时也是如此,因此您可能会看到各种结果。
java.time
使用java.time.Instant
代替java.util.Date
。
Instant
Instant
类表示UTC时间轴上的某个时刻,分辨率为纳秒(小数点后最多九位数字)。
Instant instant = Instant.ofEpochMilli( 1_330_462_800_000L ) ;
学习以UTC为主要思想和工作 。 将UTC视为一个真正的时间™。 所有其他时区仅仅是该主题的变体。 在作为程序员的工作中,忘记你的个人当地时间,并停止在区域之间来回转换,因为这可能会驱动你蝙蝠。 在您的编程和日志中关注UTC。
ZonedDateTime
要通过另一个时区的镜头查看同一时刻,请应用ZoneId
以获取ZonedDateTime
对象。 我们仍然有相同的时间点,时间轴上的同一点,但又有另一个挂钟时间。
ZoneId z = ZoneId.of( "Europe/Minsk" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
看到这个代码在IdeOne.com上运行。
instant.toString():2012-02-28T21:00:00Z
zdt.toString():2012-02-29T00:00 + 03:00 [欧洲/明斯克]
关于java.time
java.time框架内置于Java 8及更高版本中。 这些类取代了诸如java.util.Date
, Calendar
和SimpleDateFormat
等麻烦的旧式遗留日期时间类。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参阅Oracle教程。 并搜索堆栈溢出了很多例子和解释。 规范是JSR 310。
何处获取java.time类?
ThreeTen-Extra项目将java.time扩展到其他类。 这个项目是未来可能增加java.time的一个试验场。 您可以在这里找到一些有用的课程,例如Interval
, YearWeek
, YearQuarter
等。
上一篇: java.util.Date shows different values with the same input parameters