Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:为什么Calendral.setTimeInMillis(0)设置的时间不正确_Java_Android Studio_Calendar_Timezone Offset - Fatal编程技术网

Java:为什么Calendral.setTimeInMillis(0)设置的时间不正确

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。为

我的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。为什么日历时间设置为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时得到的打印输出