为了账号安全,请及时绑定邮箱和手机立即绑定

不更改时区的日期时间解析

不更改时区的日期时间解析

慕虎7371278 2022-05-12 17:18:00
我在这里有字符串类型的日期和时间值。应用日期 = 2/19/2019开始时间 = 下午 4:15我想通过 api 将一个事件插入到谷歌日历中。当我解析日期字符串时,它会根据我的本地区域设置进行转换。我住在 GMT+03.00 时区。但我想在字符串中插入日期和时间。输出:{dateTime=2019-01-19T04:15:00.000+03:00, timeZone=America/New_York}我需要得到这个:{dateTime=2019-01-19T04:15:00.000-05:00, timeZone=America/New_York}使用下面的代码块,它将晚上 8:15 插入到谷歌日历中。SimpleDateFormat formatter = new SimpleDateFormat("mm/dd/yyyy HH:mm a", Locale.US);String dateInString = appDate + " " + startTime;Date date = formatter.parse(dateInString);DateTime startDateTime = new DateTime(date);EventDateTime start = new EventDateTime().setDateTime(startDateTime).setTimeZone("America/New_York");
查看完整描述

2 回答

?
慕姐4208626

TA贡献1852条经验 获得超7个赞

java.time

您遇到了围绕遗留类和相关类的非常常见的混淆来源。java.util.Date您应该使用java.timeJava 8 中引入的较新的类:


System.out.printf("INFO - System default timezone: %s%n", ZoneId.systemDefault().getId());

// INFO - System default timezone: Europe/Moscow


// test data

String appDate = "2/19/2019";

String startTime = "4:15 PM";

String targetTimezone = "America/New_York";


String dateInString = appDate + " " + startTime;

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/d/yyyy h:mm a");

LocalDateTime ldt = LocalDateTime.parse(dateInString, formatter);

ZonedDateTime zdt = ldt.atZone(ZoneId.of(targetTimezone));


System.out.println(zdt);  // 2019-02-19T16:15-05:00[America/New_York]

如您所见,ZonedDateTime已使用正确的本地时间 (16:15 = 4:15 PM)、正确的偏移量 (-05:00) 和明确指定的时区 (America/New_York) 创建。


如果幸运的话,Google Calendar API 将能够使用这些java.time类。但是,如果您出于某种原因需要恢复为 a java.util.Date,您始终可以通过调用添加到旧类的新方法来进行转换。Instant从ZonedDateTime(从区域调整为UTC )中提取一个,然后传递给新Date.from方法。


java.util.Date date = java.util.Date.from( zdt.toInstant() );


System.out.println(date);  // Wed Feb 20 00:15:00 MSK 2019

System.out.println(date.getTime());  // 1550610900000

请注意,java.util.Date使用 JVM 的当前默认时区打印Europe/Moscow,因此已相应调整日期和时间。但是,两个值 (2019-02-19T16:15-05:00[America/New_York]和Wed Feb 20 00:15:00 MSK 2019) 都表示同一时刻:纪元 ( 1970-01-01 00:00:00 UTC) 之后的 1550610900000 毫秒。


查看完整回答
反对 回复 2022-05-12
?
慕森王

TA贡献1777条经验 获得超3个赞

SimpleDateFormat允许您指定TimeZone要解析的来源。


例如: formatter.setTimeZone(TimeZone.getTimeZone("America/New_York"));


或者,如果您只是想要一个自定义 GMT-5 时区(即:没有任何特定于位置的 DST 规则): formatter.setTimeZone(TimeZone.getTimeZone("GMT-5"));


编辑:有机会查看问题的第二部分,并查看您正在使用的日历 api - 并假设您在这里使用的 google api 类是com.google.apisgroupId、google-api-services-calendarartifactId 中的那些,那么您想要在实例化实例时还要指定TimeZone偏移量com.google.api.client.util.DateTime。


使用SimpleDateFormat指定的纽约时区将字符串“2/19/2019 4:15 PM”解析为日期,将得到一个java.util.Date包含长值 1550610900000(无论您的实际本地时区)的日期。请注意,如果您打印toString()它Date会在本地机器的时区给出一个日期。例如:对我来说,它说“Wed Feb 20 05:15:00 SGT 2019”。


通过DateTimegetTime() 从指定的 Date 中提取该 long 值,并将其存储为内部的 long 。


DateTime(或者至少是我快速尝试使用的 DateTime 类的版本(v3-rev364-1.25.0))也有一个构造函数,TimeZone它从 UTC 提取偏移量getOffset()。如果您不通过它,它将在TimeZone.getDefault().getOffset(value)内部使用。稍后当它的 toString() 被调用时,它将使用它存储的偏移量(它从时区获得)呈现它。


例子:


SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy hh:mm a", Locale.US);

formatter.setTimeZone(TimeZone.getTimeZone("America/New_York"));

Date date = formatter.parse("2/19/2019 4:15 PM");


DateTime startDateTimeNY = new DateTime(date,TimeZone.getTimeZone("America/New_York")); 

DateTime startDateTimeSG = new DateTime(date,TimeZone.getTimeZone("Asia/Singapore"));   

DateTime startDateTimeNBO = new DateTime(date,TimeZone.getTimeZone("Africa/Nairobi"));  

System.out.println(startDateTimeNY); //prints 2019-02-19T16:15:00.000-05:00

System.out.println(startDateTimeSG); //prints 2019-02-20T05:15:00.000+08:00

System.out.println(startDateTimeNBO); //prints 2019-02-20T00:15:00.000+03:00

(您可以在那里的输出中看到不同的当地时间)


我没有时间确认它,但看起来EventDateTime只是使用toString()from DateTimethe dateTime 值(如果你没有JsonFactory设置)。(它存储它的 TimeZone 用于其他目的?)


TLDR:指定 aTimeZone让SimpleDateFormat您可以从其源时区正确读取日期,并根据需要格式化输出,您还需要更改对DateTime构造函数的调用以使用所需的时区:


DateTime startDateTime = new DateTime(date,TimeZone.getTimeZone("America/New_York"));


查看完整回答
反对 回复 2022-05-12
  • 2 回答
  • 0 关注
  • 146 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信