当前位置: 首页 > 知识库问答 >
问题:

Java日历和UTC至英国夏令时的时间

云镜
2023-03-14

我得到一个格式为yyyy-MM-dd HH: mm的字符串,它代表UTC中的日期和时间。下一步是将其放入日历(带时间区UTC)。

此外,还需要创建一个单独的日历,将UTC转换为“欧洲/伦敦”时区(GMT/BST)。

之后,我需要能够检测“欧洲/伦敦”日历是否有DST(日光节约补偿)。

下面的代码将告诉你我已经走了多远,它在一台默认系统时区为GMT的英国计算机上运行正常。但是,当我在一台时区为UTC的pc上运行它时,它会失败。它似乎无法告诉我是否存在DST_偏移(它始终为零)。

      Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
    cal.set(Calendar.YEAR, 2016);
    cal.set(Calendar.MONTH, 1);
    cal.set(Calendar.DAY_OF_MONTH, 27);
    cal.set(Calendar.HOUR_OF_DAY, 23);
    cal.set(Calendar.MINUTE, 35);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);

    //This is required as Java Date JAN starts at 0.
    int MonthCon = cal.get(Calendar.MONTH)-1;
    cal.set(Calendar.MONTH, MonthCon);
    Date d = cal.getTime();



    SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz");
    f.setTimeZone(TimeZone.getTimeZone("UTC"));
    System.out.println("UTC:    " + f.format(d));
    f.setTimeZone(TimeZone.getTimeZone("Europe/London"));
    System.out.println("BST:    " + f.format(d));

    //Creates a BST calendar of the same UTC time
    String dateStrBST = f.format(d);

    SimpleDateFormat curFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz");
    curFormater.setTimeZone(TimeZone.getTimeZone("Europe/London"));
    Date dateObjBST = curFormater.parse(dateStrBST);


    System.out.println("BSTNewDate:    " + f.format(dateObjBST));


    Calendar calBST = Calendar.getInstance(TimeZone.getTimeZone("BST"));
    calBST.setTime(dateObjBST);

    System.out.println("Current TimeZone is : " +  calBST.getTimeZone());

    int offset = calBST.get(Calendar.DST_OFFSET);
    System.out.println("Day Light Savings: "+offset);
    System.out.println("Transition Day: "+isDSTTransitionDay(cal.get(Calendar.YEAR),cal.get(Calendar.MONTH),cal.get(Calendar.DAY_OF_MONTH))+"   Transition Type: "+DSTtransitionType(cal.get(Calendar.YEAR),cal.get(Calendar.MONTH),cal.get(Calendar.DAY_OF_MONTH)));

不幸的是,我需要能够检测任何特定的一天是否是过渡日,也就是说,从DST开/关或关/开变化的一天。这同样适用于本地计算机,但不适用于UTC时区1。

 private static boolean isDSTTransitionDay(int year, int month, int day) throws ParseException
 {
         Calendar calStartofDay = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
         calStartofDay.set(Calendar.YEAR, year);
         calStartofDay.set(Calendar.MONTH, month);
         calStartofDay.set(Calendar.DAY_OF_MONTH, day);
         calStartofDay.set(Calendar.HOUR_OF_DAY, 00);
         calStartofDay.set(Calendar.MINUTE, 0);
         calStartofDay.set(Calendar.SECOND, 1);            
         Date dStartofDay = calStartofDay.getTime();            

         SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz");                        
         f.setTimeZone(TimeZone.getTimeZone("Europe/London"));            
         String dateStrUTCtoBST = f.format(dStartofDay);


         SimpleDateFormat curFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz");
         curFormater.setTimeZone(TimeZone.getTimeZone("Europe/London"));
         Date dateObjBST = curFormater.parse(dateStrUTCtoBST);
         Calendar calBST = Calendar.getInstance();
         calBST.setTime(dateObjBST);            

         int offsetStart = calBST.get(Calendar.DST_OFFSET);

         calBST.add(Calendar.HOUR_OF_DAY, 23);

         int offsetEnd = calBST.get(Calendar.DST_OFFSET);
         //System.out.println("Start: "+offsetStart+" End: "+offsetEnd);




         if (offsetEnd == offsetStart) 
         {
             return false;
         }else
             {
                 //if(offsetStart<offsetEnd) {System.out.println("Transition to BST");}else{System.out.println("Transition to UTC/GMT");};
                 return true;
             }
 }

因此,在UTC计算机上,由于它总是放置日历,因此出现了严重的故障。DST_偏移量为零。我显然误解了一些事情,所以任何帮助/澄清都是好的。

在代码的其他部分使用日历时,我几乎必须保留日历,但我意识到Java8有很多更奇特的方式来做事情。

共有2个答案

廉高邈
2023-03-14

你正在使用

Calendar calBST = Calendar.getInstance();

这将calBST设置为计算机的时区(在UTC计算机上,它将是UTC)。

calBST。设置时间(dateObjBST) 设置时间,而不是时区。

试着在那里使用getInstance(时区)

在任何情况下,我会这样替换你的代码:

Calendar calStartofDay = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calStartofDay.set(Calendar.YEAR, 2017);
calStartofDay.set(Calendar.MONTH, 0);
calStartofDay.set(Calendar.DAY_OF_MONTH, 21);
calStartofDay.set(Calendar.HOUR_OF_DAY, 00);
calStartofDay.set(Calendar.MINUTE, 0);
calStartofDay.set(Calendar.SECOND, 1);            

Calendar calBST = Calendar.getInstance(TimeZone.getTimeZone("Europe/London"));
calBST.setTimeInMillis(calStartofDay.getTimeInMillis());
// use this to check the time
System.out.printf("%tc%n", calBST);

此外,从日历文档中,请注意以下事项:

set(f,value)将日历字段f更改为value。此外,它还设置了一个内部成员变量,以指示日历字段f已被更改。尽管日历字段f会立即更改,但在下一次调用get()、getTime()、getTimeInMillis()、add()或roll()之前,不会重新计算日历的时间值(以毫秒为单位)。因此,多次调用set()不会触发多次不必要的计算。使用set()更改日历字段后,其他日历字段也可能会更改,具体取决于日历字段、日历字段值和日历系统。此外,在重新计算日历字段后,get(f)不一定返回通过调用set方法设置的值。具体细节由具体的日历类决定。

马琛
2023-03-14

请允许我说实话,我试图阅读你的代码,但并不真正理解你试图获得你想要的东西的方式。如果可以使用Java8,我建议切换到使用Java8日期和时间类。有了这些,你的工作并不复杂。在我选择的去年10月30日的示威活动中,英国(和欧盟)将夏时制改为标准时间。

String originalDate = "2016-10-30 23:35";
LocalDateTime localTime = LocalDateTime.parse(originalDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
ZonedDateTime utcTime = localTime.atZone(ZoneOffset.UTC);
ZonedDateTime bstTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/London"));
// the summer time offset is how many milliseconds?
long dstOffset = ChronoUnit.MILLIS.between(utcTime.toLocalDateTime(), bstTime.toLocalDateTime());
System.out.println(dstOffset); // prints 0

// try the same at start of day (midnight)
utcTime = utcTime.toLocalDate().atStartOfDay(ZoneOffset.UTC);
bstTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/London"));
dstOffset = ChronoUnit.MILLIS.between(utcTime.toLocalDateTime(), bstTime.toLocalDateTime());
System.out.println(dstOffset); // prints 3600000

// and next midnight
utcTime = utcTime.plusDays(1);
bstTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/London"));
dstOffset = ChronoUnit.MILLIS.between(utcTime.toLocalDateTime(), bstTime.toLocalDateTime());
System.out.println(dstOffset); // prints 0
 类似资料:
  • 2018-03-26 09:04:14Z 2018-03-26 14:34:14+05:30 2018-03-26 11:04:14+02:00

  • 从“GMT夏令时”或任何其他可用的Windows时区信息有什么方法可以到达BST吗?

  • 如果英国是格林尼治标准时间(一年的一半),这工作良好时,投入一个活动。然而,在英国夏令时,该事件在创建时会延迟一个小时。如何输入时区或创建正确处理GMT或BST的日期。还有没有更好的方法来完成我到目前为止所做的事情呢? 多谢。

  • 我有一个日历对象的问题,它没有显示美国/圣地亚哥时区的DST(每日节约时间)的正确偏移:我的示例代码:time zone from time zone = time zone . gettimezone("美国/圣地亚哥"); 输出为:偏移量:-4在2015年3月31日的美国/圣地亚哥时区,偏移量应为-3。(参考:http://www.timeanddate.com/worldclock/conv

  • 问题内容: SQL Server作业/计划-美国与英国夏令时调整 我们有一台基于英国的服务器,需要在16:30(美国中部时间-这可能很奇怪,但这是由于某些数据的可用性)运行SQL Agent Job。通常这不会造成问题,因为英国和美国之间的时差为6个小时,因此我们将工作安排在22:30进行。 但是,由于英美两国在3月和11月的不同时间调整时钟以节省夏令时,因此英美之间的时差为5个小时,为2周。 我

  • 我有一个Java客户机,它正在以UTC格式在MySQL DB中插入(通过CSV和'Load DATA Infile')时间戳(type TIMESTAMP)。我的服务器的时区是“America/New_York”,我需要保留夏令时信息。11月5日凌晨2点是美国东部时间转换到东部时间的时候,时钟拨回一个小时到凌晨1点。例如,11月5日凌晨1:30,发生两次;EDT和EST各一次。 我该如何让服务器区