Java日历和UTC到BST的时间

Java日历和UTC到BST的时间,java,datetime,calendar,java-8,Java,Datetime,Calendar,Java 8,我得到一个格式为yyyy-MM-dd-HH:MM的字符串,它表示UTC中的日期和时间。 下一步是将其放入日历(使用时区UTC) 此外,还需要创建一个单独的日历,将UTC转换为“欧洲/伦敦”时区(GMT/BST) 在此之后,我需要能够检测“欧洲/伦敦”日历是否有DST(日光节约偏移) 下面的代码将向您显示我已经走了多远,它在一台默认系统时区为GMT的英国计算机上运行正常。但是,当我在一台时区为UTC的pc上运行它时,它会失败。它似乎无法告诉我是否存在DST_偏移(它始终为零) 不幸的是,我需要能够

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

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

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

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

不幸的是,我需要能够检测任何特定的一天是否是过渡日,也就是说,从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;
             }
 }
private静态布尔值isDSTTransitionDay(整年、整月、整日)抛出异常
{
Calendar calStartofDay=Calendar.getInstance(TimeZone.getTimeZone(“UTC”);
calStartofDay.set(日历年、年份);
calStartofDay.set(Calendar.MONTH,MONTH);
calStartofDay.set(Calendar.DAY\u/u月,天);
calStartofDay.set(Calendar.HOUR\u OF_DAY,00);
calStartofDay.set(Calendar.MINUTE,0);
calStartofDay.set(日历秒,1);
Date-dStartofDay=calStartofDay.getTime();
SimpleDataFormat f=新的SimpleDataFormat(“yyyy-MM-dd HH:MM:ssz”);
f、 设置时区(TimeZone.getTimeZone(“欧洲/伦敦”);
字符串dateStrUTCtoBST=f.format(dStartofDay);
SimpleDataFormat curformat=新的SimpleDataFormat(“yyyy-MM-dd HH:MM:ssz”);
curformatter.setTimeZone(TimeZone.getTimeZone(“欧洲/伦敦”);
Date dateObjBST=curformatter.parse(dateStrUTCtoBST);
Calendar calBST=Calendar.getInstance();
计算设置时间(dateObjBST);
int offsetStart=calBST.get(Calendar.DST_OFFSET);
calBST.add(Calendar.HOUR\u OF_DAY,23);
int offsetEnd=calBST.get(Calendar.DST_OFFSET);
//系统输出打印项次(“开始:+offsetStart+”结束:+offsetEnd);
if(offsetEnd==offsetStart)
{
返回false;
}否则
{
//如果(offsetStart您正在使用

Calendar calBST = Calendar.getInstance();
这将calBST设置为计算机的时区(在UTC计算机上,它将是UTC)

calBST.setTime(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)不一定会返回调用集合所设置的值 方法在重新计算日历字段之后。详细信息 由具体的日历类确定


请允许我说实话,我试图阅读您的代码,但并不真正理解您获取所需内容的方式。如果您可以使用Java 8,我建议您改用Java 8日期和时间类。使用这些类,您的工作并不复杂。对于我选择的演示,我选择了去年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

好了,UTC从来没有DST。GMT不等于UTC。“UTC计算机它失败得很惨,因为它总是将Calendar.DST_偏移量设置为零”根据定义,它应该始终是零的偏移量。您希望它做什么?顺便说一句,在法语中,UTC在巴黎定义为1,而不是在伦敦。另外,为什么在设置所有值后,您要从月份中减去一?换句话说,您首先设置的月份不正确,然后进行更正。最好从一开始就正确设置:
cal。set(Calendar.MONTH,0)
或者更好的
cal.set(Calendar.MONTH,Calendar.janur)
。它尝试了:Calendar calBST=Calendar.getInstance(TimeZone.getTimeZone(“Europe/London”);但结果是java.lang.NullPointerException。如果我使用“UTC”很好?在我的电脑上,我没有收到NullPointerException,我尝试了不同的城市…从“getTimeZone”文档:“返回:指定的时区,如果给定的ID无法理解,则返回GMT区域。”所以很奇怪,你有一个NPEI,我正在AWS Lambda上运行这个…如果这有什么区别的话。你有没有可能去chatFYI,旧的日期时间类,比如,和
java.text.SimpleTextFormat
现在被这些类取代了。
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