简体   繁体   English

如何将时间戳转换为日期

[英]How convert Timestamp to Date

Other system send for us Timestamp in their time zone.If we run that in cloud in other system is +2 hours. 其他系统会在他们所在的时区为我们发送时间戳。如果在其他系统中在云中运行,则需要+2小时。 Local is good because the server is the same time zone. 本地是好的,因为服务器是相同的时区。 How can I be sure that the time will always be right? 我如何确定时间永远正确?

String TIME_STAMP_FORMAT = "yyyy-MM-dd-HH.mm.ss.SSSSSS";

DateTimeFormatter TIME_STAMP_FORMATTER = DateTimeFormatter.ofPattern(TIME_STAMP_FORMAT, Locale.getDefault());

private static Timestamp parseTimestamp(String dateString) {
        try {
            return Timestamp.valueOf(LocalDateTime.parse(dateString, TIME_STAMP_FORMATTER));
        } catch (DateTimeParseException e) {
            log.error("Not able to parse timestamp", e);
        }
        return null;
    }

Date afterParse =  parseTimestamp('2018-12-31-12.30.50.000200')

tl;dr TL;博士

How can I be sure that the time will always be right? 我如何确定时间永远正确?

  • Include an indicator of time zone or offset-from-UTC with your date-time input string. 在日期时间输入字符串中包括时区UTC偏移量指示器。
  • Use standard ISO 8601 formats when exchanging date-time values. 交换日期时间值时,请使用标准的ISO 8601格式。
  • Use only java.time classes in Java. 在Java中仅使用java.time类。 Never use Date , Timestamp , Calendar , etc. 切勿使用DateTimestampCalendar等。
  • Tip: Adjust values from other zones to UTC before sending (generally speaking). 提示:在发送之前(通常来说),请将其他区域的值调整为UTC。

If not possible, then here is a workaround. 如果不可能,那么这里是一种解决方法。 This assumes you know the time zone intended by the sender of this poor data. 假定您知道此不良数据的发送者所预期的时区。

LocalDateTime                           // Represent a date and time-of-day without the context of a time zone or offset-from-UTC. NOT a moment, NOT a point on the timeline. A meaningless value until you assign a zone/offset.
.parse(
    "2018-12-31-12.30.50.000200" ,      // Avoid such custom formats. Use only ISO 8601 when exchanging date-time values textually.
    DateTimeFormatter.ofPattern( "uuuu-MM-dd-HH.mm.ss.SSSSSS" )  // Define formatting pattern to match youre input.
)                                       // Returns a `LocalDateTime` object.
.atZone(                                // Give meaning to the `LocalDateTime` object by applying a time zone.
    ZoneId.of( "Africa/Tunis" )         // Always specify a time zone with `Continent/Region` name, never the 2-4 character pseudo-zones popularly seen in the media.
)                                       // Returns a `ZonedDateTime` object.
.toInstant()                            // Adjust from a time zone to UTC by extracting an `Instant` object. Same moment, same point on the timeline, different wall-clock time.

See this code run live at IdeOne.com . 看到此代码在IdeOne.com上实时运行

Best to avoid java.util.Date class. 最好避免使用java.util.Date类。 But if you must interoperate with old code not yet updated to java.time , you can convert. 但是,如果必须与尚未更新为java.time的旧代码进行互操作,则可以进行转换。 Call on the new methods added to the old classes such as Date.from( Instant ) . 调用添加到旧类中的新方法,例如Date.from( Instant )

Avoid legacy classes 避免遗留类

Never use java.sql.Timestamp nor java.util.Date . 切勿使用java.sql.Timestampjava.util.Date All of the date-time classes bundled with the earliest versions of Java are now legacy, per the adoption of JSR 310. Use only the modern java.time classes. 根据JSR 310的使用,与最早的Java版本捆绑在一起的所有日期时间类现在都是旧式的。仅使用现代的java.time类。

Wrong data type 数据类型错误

You are using the wrong data type. 您使用了错误的数据类型。 To track a moment, a specific point on the timeline, you must have a time zone or offset-from-UTC. 要跟踪时刻,即时间轴上的特定点,您必须具有时区或UTC偏移量。 The LocalDateTime class exactly the wrong class to use here. LocalDateTime类恰好在这里使用了错误的类。 That class purposely lacks any concept of zone or offset. 该类故意缺少区域或偏移的任何概念。 So it is the opposite of what you want. 因此,这与您想要的相反。

To track a moment, use Instant , OffsetDateTime , or ZonedDateTime . 要跟踪时刻,请使用InstantOffsetDateTimeZonedDateTime

Java中的日期时间类型表,包括现代的和传统的。

Where the java.time classes have methods with an optional time zone ( ZoneId ) or offset-from-UTC ( ZoneOffset ) argument, consider the argument required. 如果java.time类的方法带有可选的时区( ZoneId )或自UTC偏移量( ZoneOffset )参数,请考虑所需的参数。 Always pass a zone/offset. 始终通过区域/偏移。 Then you never need worry about how the sysadmin is setting the JVM's current default time zone at runtime. 然后,您无需担心sysadmin在运行时如何设置JVM的当前默认时区。

ZonedDateTime.now(                    // Capture the current moment as seen through the wall-clock time used by the people of a particular region (a time zone).
    ZoneId.of( "Pacific/Auckland" )
)

Or, use Instant which is always in UTC, by definition. 或者,根据定义,始终使用UTC中的Instant

Instant.now()                         // Capture the current moment in UTC.

Specify a proper time zone name in the format of Continent/Region , such as America/Montreal , Africa/Casablanca , or Pacific/Auckland . Continent/Region的格式指定正确的时区名称 ,例如America/MontrealAfrica/CasablancaPacific/Auckland Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!). 切勿使用2-4字母的缩写,例如ESTIST因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。

ISO 8601 ISO 8601

Your question is not clear, but it seems you are receiving an input string for a date-time in a custom format. 您的问题尚不清楚,但似乎您正在接收自定义格式的日期时间输入字符串。 I suggest you educate the people publishing that data about the ISO 8601 standard. 我建议您教育人们发布有关ISO 8601标准的数据。 This standard defines practical formats for date-time values being exchanged between systems textually. 该标准定义了文本之间在系统之间交换的日期时间值的实用格式。

The java.time classes use the ISO 8601 formats by default when parsing/generating strings. 解析/生成字符串时, java.time类默认使用ISO 8601格式。

Workaround 解决方法

If the data publisher is sending you values such as 2018-12-31-12.30.50.000200 in order to communicate a moment, they have failed. 如果数据发布者向您发送诸如2018-12-31-12.30.50.000200值以便进行交流,则它们已失败。 A date and time-of-day without a zone or offset is useless, like communicating an amount of money without indicating a currency. 没有区域或偏移量的日期和时间是无用的,就像在不指示货币的情况下传达一定数量的钱一样。

Do you know for certain the time zone that was implicitly assumed by the sender of this faulty data input? 您是否肯定知道此错误数据输入的发送者隐式假定的时区? If so, apply it, as a clumsy stop-gap measure for their poor practice. 如果是这样,请应用它,作为对他们的不良实践的笨拙的权宜之计。

First parse your input as a LocalDateTime given that it lacks any indicator of zone/offset. 考虑到输入缺少区域/偏移量的指示,请首先将其解析为LocalDateTime

String input = "2018-12-31-12.30.50.000200" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd-HH.mm.ss.SSSSSS" ) ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;

Apply a ZoneId to get a ZonedDateTime object, thereby adjusting to view the moment through the wall-clock time used by the people of that particular region. 应用ZoneId以获取ZonedDateTime对象,从而进行调整以查看该特定地区的人们使用的挂钟时间的时刻。

ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = ldt.atZone( ldt ) ;

Generally best to work with moments in UTC , unless you have a specific reason to use a time zone (such as presentation to user). 通常,最好使用UTC中的时刻,除非您有特定的理由使用时区(例如向用户演示)。 So extract an Instant from your ZonedDateTime . 因此,从您的ZonedDateTime提取一个Instant

Instant instant = zdt.toInstant() ;

The Z at the end of an ISO 8601 compliant string means UTC, and is pronounced “Zulu”. 符合ISO 8601的字符串末尾的Z表示UTC,并发音为“ Zulu”。

See this code run live at IdeOne.com . 看到此代码在IdeOne.com上实时运行

input: 2018-12-31-12.30.50.000200 输入:2018-12-31-12.30.50.000200

ldt: 2018-12-31T12:30:50.000200 ldt:2018-12-31T12:30:50.000200

zdt: 2018-12-31T12:30:50.000200+09:00[Asia/Tokyo] zdt:2018-12-31T12:30:50.000200 + 09:00 [亚洲/东京]

instant: 2018-12-31T03:30:50.000200Z 即时:2018-12-31T03:30:50.000200Z


About java.time 关于java.time

The java.time framework is built into Java 8 and later. java.time框架内置于Java 8及更高版本中。 These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat . 这些类取代了麻烦的旧的旧式日期时间类,例如java.util.DateCalendarSimpleDateFormat

To learn more, see the Oracle Tutorial . 要了解更多信息,请参见Oracle教程 And search Stack Overflow for many examples and explanations. 并在Stack Overflow中搜索许多示例和说明。 Specification is JSR 310 . 规格为JSR 310

The Joda-Time project, now in maintenance mode , advises migration to the java.time classes. 现在处于维护模式Joda-Time项目建议迁移到java.time类。

You may exchange java.time objects directly with your database. 您可以直接与数据库交换java.time对象。 Use a JDBC driver compliant with JDBC 4.2 or later. 使用与JDBC 4.2或更高版本兼容的JDBC驱动程序 No need for strings, no need for java.sql.* classes. 不需要字符串,不需要java.sql.*类。

Where to obtain the java.time classes? 在哪里获取java.time类?

The ThreeTen-Extra project extends java.time with additional classes. ThreeTen-Extra项目使用其他类扩展了java.time。 This project is a proving ground for possible future additions to java.time. 该项目为将来可能在java.time中添加内容提供了一个试验场。 You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more . 您可以在这里找到一些有用的类,比如IntervalYearWeekYearQuarter ,和更多

Just a small supplement to Basil Bourque's clever and very informative answer . 罗勒·布尔克(Basil Bourque)巧妙而又翔实的答案只是一个小补充。

  1. I know the date is in CET timezone. 我知道日期是CET时区。

I am sorry, this is not enough. 对不起,这还不够。 Central European Time (CET) is the common term for quite many European and African(!) time zones the details of which differ. 中欧时间(CET)是许多欧洲和非洲(!)时区的通用术语,其时区有所不同。 The European ones are generally at offset +01:00 during standard time and at +02:00 during summer (known as Central European Summer Time or CEST). 欧洲标准时间通常在标准时间为+01:00,夏季为+02:00(称为中欧夏季时间或CEST)。 The African ones are at +01:00 all year. 非洲人全年都在+01:00。 For past dates, just a few decades back, some zones used summer time (DST), others didn't, some were at +00:00, +01:00 or +02:00, and further back in history many other offsets were used, generally not whole hours. 对于过去的日期,仅几十年前,一些区域使用夏令时(DST),其他区域则没有使用夏令时,一些区域则在+00:00,+ 01:00或+02:00,并且在历史上还有许多其他偏移使用,通常不是整个小时。

The future is even worse! 未来更糟! It has been suggested that the European Union abandons summer time and leaves it to each member state whether they will use permanent standard time or permanent summer time, avoiding the time adjustments in spring and autumn. 有人建议欧洲联盟放弃夏令时,将其留给每个成员国使用永久标准时间还是永久夏令时,避免在春季和秋季进行时间调整。 There is a power struggle going on about this, so we don't know whether it will happen, nor what each member state chooses. 正在进行一场权力斗争,所以我们不知道它是否会发生,也不知道每个成员国会选择什么。 So even if you could tell me the exact time zone of your string from the other system (for example, Europe/Sarajevo), no one knows yet whether 2019-11-01-00.30.50.000200 — less than 7 months from now — will be at offset +01:00 or +02:00. 因此,即使您可以从另一个系统(例如,欧洲/萨拉热窝)告诉我您字符串的确切时区,也没人知道2019-11-01-00.30.50.000200 (从现在开始不到7个月)是否会偏移+01:00或+02:00。

Link: European MPs vote to end summer time clock changes on BBC News. 链接: 欧洲国会议员投票结束 BBC新闻的夏季时钟更改

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM