首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何解析日期时间并将其与相应的时区关联

如何解析日期时间并将其与相应的时区关联
EN

Stack Overflow用户
提问于 2019-12-24 20:16:33
回答 3查看 553关注 0票数 0

我试图以2019-12-23 13:35:00格式读取一个字符串,以创建一个DateTime对象,并将其与我所知道的特定时区相关联(GMT-5)。

我试着这样做:

代码语言:javascript
复制
 val string1 = "2019-12-23 13:35:00"
    val sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    sdf.setTimeZone(StaticDateTimeZone.forID("Etc/GMT-5").toTimeZone)
    val date = sdf.parse(string1)

输出不是我想要的,因为它不是假设日期时间不在GMT-5时区,而是在我的系统的时区(GMT+0)中,将日期时间调整为GMT-5,如下所示:Mon Dec 23 08:35:00 GMT 2019

如何创建不更改输入的datetime对象,并将时区与其关联?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-12-24 21:59:44

(使用Java语法而不是Scala)

tl;dr

我知道它对应的特定时区(格林尼治标准时间-5)

GMT-5,不是时区,它只是偏移量。时区具有Continent/Region格式的名称,如Africa/Tunis。时区是区域使用的偏移量变化的历史记录。

无法从偏移量可靠地确定时区。许多时区在某一特定时刻可能共享相同的偏移量,但在其他时刻则可能有所不同。所以你只会胡思乱想。只有当您确实了解特定区域时,才应用时区。

相反,使用偏移量本身来确定时间,而不是区域。这里有一个单行解决方案。

代码语言:javascript
复制
LocalDateTime                                     // Represent a date with time-of-day but lacking the context of an offset-from-UTC or a time zone.
.parse(                                           // When parsing, no need to specify a formatting pattern when the input complies with the ISO 8601 standard.        
    "2019-12-23 13:35:00".replace( " " , "T" )    // Comply with ISO 8601 standard formatting, replacing SPACE in the middle with an uppercase `T`. 
)                                                 // Returns a `LocalDateTime` object.
.atOffset(                                        // Determine a moment by placing the date and time-of-day of a `LocalDateTime` into the context of an offset-from-UTC.
    ZoneOffset.ofHours( -5 )                      // Represent an offset-from-UTC with `ZoneOffset`, merely a number of hours-minutes-seconds ahead or behind the prime meridian. 
)                                                 // Returns a `OffsetDateTime` object.
.toString()                                       // Generate text in standard ISO 8601 format.

实时运行代码

2019-12-23T13:35-05:00

java.time

ISO 8601

您的输入字符串几乎采用ISO 8601标准格式。若要符合要求,请将中间的空格替换为T

代码语言:javascript
复制
String input = "2019-12-23 13:35:00".replace( " " , "T" ) ;

LocalDateTime

考虑到输入缺少时区或偏离-UTC,请将其解析为LocalDateTime

代码语言:javascript
复制
LocalDateTime ldt = LocalDateTime.parse( input ) ;

请注意,LocalDateTime不是一个瞬间,也不是时间线上的一个点。在你的例子大约下午1:30,我们不知道这是否意味着下午1:30在日本东京或下午1:30下午1:30在俄亥俄州托莱多,两个非常不同的时刻相隔许多小时。

OffsetDateTime

您可以肯定地知道,这个日期和时间是通过UTC后5小时(通常是在主子午线以西)偏移的镜头看到的。

代码语言:javascript
复制
ZoneOffset offset = ZoneOffset.ofHours( -5 ) ;  // Five hours before UTC.

因此,让我们应用这个ZoneOffset来获得一个OffsetDateTime

代码语言:javascript
复制
OffsetDateTime odt = ldt.atOffset( offset ) ;

看这个在IdeOne.com现场运行的代码

odt.toString():2019-12-23T13:35-05:00

ZonedDateTime

时区总是比与世界协调时相距更好的时区.偏移是几个小时--分-秒,仅此而已。时区更重要。时区是过去、现在和未来对特定地区人民使用的偏移量的变化的历史。

但不要在时区猜测。仅当您知道LocalDateTime对象最初用于该区域时,才应用区域。

Continent/Region格式指定Continent/Region,如America/MontrealAfrica/CasablancaPacific/Auckland。不要使用2-4字母的缩写,如ESTIST,因为它们不是真正的时区,不标准化,甚至不是唯一的(!)。

代码语言:javascript
复制
ZoneId z = ZoneId.of( "America/Panama" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;

关于java.time

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/package-summary.html框架内置到Java8和更高版本中。这些类取代了麻烦的旧遗赠日期时间类,如java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参见http://docs.oracle.com/javase/tutorial/datetime/TOC.html。并搜索堆栈溢出以获得许多示例和解释。规范是JSR 310

http://www.joda.org/joda-time/项目现在在维护模式中,建议迁移到java.time类。

您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC 4.2。不需要字符串,也不需要java.sql.*类。

在哪里获得java.time类?

  • Java 8Java 9Java 10Java 11和更高版本--捆绑实现的标准Java的一部分。
    • Java 9添加了一些次要的特性和修复。

  • Java 6Java 7
    • 大多数java.time功能都是在http://www.threeten.org/threetenbp/中移植到Java6&7中的。

  • 安卓
    • 较晚版本的Android实现的java.time类。
    • 对于早期的Android (<26),https://github.com/JakeWharton/ThreeTenABP项目采用了http://www.threeten.org/threetenbp/ (上面提到的)。见http://stackoverflow.com/q/38922754/642706

三次-额外项目使用其他类扩展java.time。这个项目是将来可能加入java.time的试验场。您可以在这里找到一些有用的类,如IntervalYearWeekYearQuarter更多

票数 4
EN

Stack Overflow用户

发布于 2019-12-24 20:42:31

您似乎正在使用JodaTime,然后转换为java.util.Date。您可以直接使用Java8中的java.time包:

代码语言:javascript
复制
val string1 = "2019-12-23 13:35:00"
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
val date = LocalDateTime.parse(string1, formatter)
date.atZone(ZoneId.of("Etc/GMT-5"))

这意味着:

代码语言:javascript
复制
date: java.time.LocalDateTime = 2019-12-23T13:35
res0: java.time.ZonedDateTime = 2019-12-23T13:35+05:00[Etc/GMT-5]

LocalDateTime生成没有附加任何时区的日期。最后一行有效地从前一个日期创建一个新的ZonedDateTime,并在上面添加给定的时区。如果您需要返回java.util.Date,请参阅这个答案

票数 4
EN

Stack Overflow用户

发布于 2019-12-24 21:20:16

例如,我编写了一个方法:

代码语言:javascript
复制
    public static Date getDateWithTimeZone(String dateString, String format, String timeZone) {
        DateFormat df = new SimpleDateFormat(format);
        Date dateObj = null;

        try {
            dateObj = df.parse(dateString);
            DateTime dateTime = new DateTime(dateObj);
            TimeZone zone = TimeZone.getTimeZone(timeZone);
            return dateTime.withZoneRetainFields(DateTimeZone.forTimeZone(zone))
                    .toDate();
        } catch (ParseException e) {
            logger.error("Error while converting string to date",e);
        }
        return null;
    }
  • 您可以根据需要更改方法/异常处理。希望这能有所帮助。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59473083

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档