Java:为什么Calendral.setTimeInMillis(0)设置的时间不正确
我的Android应用程序(在java中,在Android Studio中)使用类“Calendar”。之后Java:为什么Calendral.setTimeInMillis(0)设置的时间不正确,java,android-studio,calendar,timezone-offset,Java,Android Studio,Calendar,Timezone Offset,我的Android应用程序(在java中,在Android Studio中)使用类“Calendar”。之后 Calendar cal=Calendar.getInstance(); cal.setTimeInMillis(0); Log.i("Interim",cal.getTime().toString()); 这样的输出正在产生:I/临时:星期四1月1日03:00:00 GMT+02:00 1970。我的时区是GMT+02:00(乌克兰基辅),不适用1月份的DST。为
Calendar cal=Calendar.getInstance();
cal.setTimeInMillis(0);
Log.i("Interim",cal.getTime().toString());
这样的输出正在产生:I/临时:星期四1月1日03:00:00 GMT+02:00 1970
。我的时区是GMT+02:00(乌克兰基辅),不适用1月份的DST。为什么日历时间设置为03:00?我期望00:00(不考虑时区)或02:00(考虑时区),但为什么是03:00
提前谢谢你的建议
PS为了澄清情况,我将日历时区设置为GMT并获取小时值:
Calendar cal=Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.setTimeInMillis(0);
Log.i("Interim hours",Integer.toString(cal[i].get(Calendar.HOUR)));
Log.i("Interim",cal.getTime().toString());
与预期相反,产量为:
I/临时时间:0
临时:星期四一月一日03:00:00 GMT+1970年02:00
所以,小时字段的值是0,但时间是03:00。
我刚刚听说1975年6月13日轮班1小时(见下面的答案),但这似乎只与越南TZ有关,不是吗?如果您的输入在1975年6月13日之前,结果总是+1小时。那天有25个小时。你可以查一下。如果输入1975年6月13日,我们得到171824400000,而1975年6月12日,我们得到171734400000
171824400000-171734400000=90000000
90000000/(60*60*1000)=25(?)
所以我认为如果你的输入在1975年6月13日之前,你可以加1小时,如果你的输入在1975年6月13日之前,结果总是+1小时。那天有25个小时。你可以查一下。如果输入1975年6月13日,我们得到171824400000,而1975年6月12日,我们得到171734400000
171824400000-171734400000=90000000
90000000/(60*60*1000)=25(?)
因此,如果您在1975年6月13日之前输入,我想您可以再加1个小时。请区分时区和偏移量。您的时区是欧洲/基辅(如果存在英语拼写,则使用时区ID中地名的英语拼写)。欧洲/基辅1月份的偏移量为+02:00。由于夏季时间(夏令时,DST),10月27日之前的偏移量为+03:00,从3月29日起再次出现。让一些人吃惊的是,从1944年到1980年,它一直处于偏移量+03:00。所以在1970年1月1日00:00 UTC时,乌克兰的时间是3:00。因此,对于乌克兰来说,这部分输出是正确的
简而言之:时区包含该时区使用的UTC/GMT的历史、当前和已知未来偏移量。GMT+02:00是偏移量,不是时区
java.time和ThreeTenABP
以下是获得我认为你想要的东西的现代方式:
ZonedDateTime epochInUkraine = Instant.EPOCH.atZone(ZoneId.of("Europe/Kiev"));
System.out.println(epochInUkraine);
这些行的输出为:
1970-01-01T03:00+03:00[欧洲/基辅]
如果您想要一个类似于打印老式java.util.Date
对象时得到的打印输出:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
"EEE MMM dd HH:mm:ss zzz yyyy", Locale.ROOT);
System.out.println(epochInUkraine.format(formatter));
1970年1月1日星期四03:00:00 EET
不过,您可能会找到更适合您的受众的输出格式。我把那部分留给你自己
出了什么问题?
为什么Calendar.setTimeInMillis(0)
设置的时间不正确
事实并非如此。Calendar
类及其子类的设计很差,而且很早就过时了,但是setTimeInMillis(0)
设置了正确的时间。您还注意到,当您的日历
使用UTC时,其上午或下午的时钟小时数(0到11)为0。在03:00和+02:00之间存在矛盾的情况下,您是如何得到03:00:00 GMT+02:00
的输出的?可能的解释包括:
- 很可能是你这边的错误。这可能不是来自您设置为0的
日历,也可能是您在键入问题时复制了不准确的输出。如果你再检查一次你是否能复制这个输出,我很想听听
Date.toString()
中不太可能出现错误,当您打印从cal.getTime()
获得的Date
时,会隐式调用该错误
- 更不可能是
Calendar.getTime()
中的错误,它从Calendar
中为您提供了错误的Date
对象
问:java.time不需要Android API级别26吗?
time在较旧和较新的Android设备上都能很好地工作。它至少需要Java6
- 在Java8和更高版本以及更新的Android设备上(API级别26),现代API是内置的
- 在非androidjava6和7中,获取三个后端口,即现代类的后端口(三个十用于jsr310;请参见底部的链接)
- 在(较旧的)Android上使用Android版本的ThreeTen Backport。它叫ThreeTenABP。并确保从带有子包的
org.threeten.bp
导入日期和时间类
链接
- 显示历史和未来的偏移量
- 解释如何使用java.time
- ,其中首先描述了
java.time
- ,java.time的后端口
到Java6和Java7(JSR-310为三十)
,Android版Three Ten Backport
,解释得非常透彻
请区分时区和偏移量。您的时区是欧洲/基辅(如果存在英语拼写,则使用时区ID中地名的英语拼写)。欧洲/基辅1月份的偏移量为+02:00。由于夏季时间(夏令时,DST),10月27日之前的偏移量为+03:00,从3月29日起再次出现。让一些人吃惊的是,从1944年到1980年,它一直处于偏移量+03:00。所以在1970年1月1日00:00 UTC时,乌克兰的时间是3:00。因此,对于乌克兰来说,这部分输出是正确的
简而言之:时区包含该时区使用的UTC/GMT的历史、当前和已知未来偏移量。GMT+02:00是偏移量,不是时区
java.time和ThreeTenABP
以下是获得我认为你想要的东西的现代方式:
ZonedDateTime epochInUkraine = Instant.EPOCH.atZone(ZoneId.of("Europe/Kiev"));
System.out.println(epochInUkraine);
这些行的输出为:
1970-01-01T03:00+03:00[欧洲/基辅]
如果您想要一个类似于打印老式java.uti时得到的打印输出