Java 将 19 位 Unix 时间戳转换为可读日期

mrT*_*mrT 1 java unix-timestamp datetime-conversion

我正在尝试将 19 位 Unix 时间戳(例如(五分之一))转换1558439504711000000可读的日期/时间格式。我的时间戳以 6 个零结尾,这表明时间以纳秒为单位。

我遇到过一些例子,人们使用了我不需要的时区。另一个例子使用 ofEpochSecond ,如下所示:

Instant instant = Instant.ofEpochSecond(seconds, nanos);
Run Code Online (Sandbox Code Playgroud)

但我不确定是否需要使用ofEpochSecond。

下面的代码给出了我实现这一目标的最新方法:

String timeStamp = "1558439504711000000";
long unixNanoSeconds = Long.parseLong(timeStamp);
Date date = new java.util.Date(timeStamp*1000L); 
// My preferred date format
SimpleDateFormat sdf = new java.text.SimpleDateFormat("dd-MM-yyyy HH:mm:ss");                    
String formattedDate = sdf.format(date);
System.out.println("The timestamp in your preferred format is: " +  formattedDate); 
Run Code Online (Sandbox Code Playgroud)

但我得到的输出是这样的:

// The timestamp in your preferred format is: 11-12-49386951 11:43:20
Run Code Online (Sandbox Code Playgroud)

其中不显示年份格式,例如 2019 格式。

Bas*_*que 5

太长了;博士

\n\n

切勿使用遗留类java.util.Date。相反,使用现代java.time.Instant.

\n\n
Instant                                  // The modern way to represent a moment in UTC with a resolution of nanoseconds. Supplants the terrible `java.util.Date` class.\n.ofEpochSecond(                          // Parse a count since epoch reference of 1970-01-01T00:00:00Z.\n    0L ,                                 // Passing zero for the count of whole seconds, to let the class determine this number from the 2nd argument.\n    Long.parse( "1558439504711000000" )  // Count of nanoseconds since the epoch reference of 1970-01-01T00:00:00Z. \n)                                        // Returns a `Instant` object.\n.atZone(                                 // Adjust from UTC to the wall-clock time used by the people of a specific region (a time zone).\n    ZoneId.of( "Europe/London" ) \n)                                        // Returns a `ZonedDateTime` object. Same moment as the `Instant`, same point on the timeline, different wall-clock time.\n.format(                                 // Generate text to communicate the value of the moment as seen through this time zone.\n    DateTimeFormatter.ofPattern(         // Define how to format our generated text.\n        "dd-MM-uuuu HH:mm:ss" ,          // Specify your desired formatting pattern.\n        Locale.UK                        // Pass a `Locale` to be used in localizing, to (a) determine human language used in translating name of day-of-week and such, and (b) determine cultural norms to decide issues of capitalization, abbreviation, etc. Not really needed for this particular formatting pattern, but a good habit to specify `Locale`.\n    )                                    // Returns a `DateTimeFormatter` object.\n)                                        // Returns a `String` object containing our text.\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

21-05-2019 12:51:44

\n
\n\n

\xe2\x80\xa6 或 \xe2\x80\xa6

\n\n
Instant\n.ofEpochSecond (\n    TimeUnit.NANOSECONDS.toSeconds( \n       Long.parse( "1558439504711000000" ) \n    ) ,\n    ( 1_558_439_504_711_000_000L % 1_000_000_000L )\n)\n.toString()\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

2019-05-21T11:51:44.711Z

\n
\n\n

请注意时差,因为时区比 UTC 早一小时。

\n\n

避免遗留日期时间类

\n\n

班级java.util.Date糟糕。连同它的同窝动物,例如Calendar& SimpleDateFormat,它们简直是一团糟。避开他们。Sun、Oracle 和 JCP 社区在采用 JSR 310 后放弃了它们。

\n\n

Instant

\n\n

一个java.util.Date对象代表UTC中的一个时刻,分辨率为毫秒。它的替代品也是java.time.InstantUTC 中的时刻,但分辨率为纳秒在内部,两者都跟踪自 UTC 1970 第一个时刻纪元参考以来的计数。

\n\n

为了避免处理巨大的数字,a 在内部Instant跟踪自 1970 年以来的整秒数以及保存为纳秒数的小数秒。两个独立的数字。这些就是你需要喂养的东西Instant.ofEpochSecond

\n\n

将您的输入字符串解析为long使用Long类。顺便说一句,请注意您的值正在接近64 位整数的限制

\n\n
long totalNanos = Long.parse( "1558439504711000000" ) ;\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用枚举来计算分割整秒的数学。TimeUnit

\n\n
long secondsPortion = TimeUnit.NANOSECONDS.toSeconds( totalNanos ) ;\n
Run Code Online (Sandbox Code Playgroud)\n\n

以十亿为模,余数为小数秒的纳秒。

\n\n
long nanosPortion = ( totalNanos % 1_000_000_000L ) ;\n
Run Code Online (Sandbox Code Playgroud)\n\n

实例化一个Instant.

\n\n
Instant instant = Instant.ofEpochSecond( secondsPortion , nanosPortion ) ;\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

我的时间戳以 6 个零结尾,这表明时间以纳秒为单位。

\n
\n\n

实际上,纳秒计数可达十亿,因此是九 (9) 位数字而不是六 (6)。从纪元开始计数的小数秒是711000000, 或 711,000,000 纳秒。您的整秒数是1558439504, 或 1,558,439,504(五亿五)。作为小数:

\n\n

自 1970-01-01T00:00Z 以来的 1,558,439,504.711000000 秒

\n\n

时区

\n\n
\n

我遇到过一些例子,人们使用了我不需要的时区。

\n
\n\n

要表示某个时刻(时间轴上的特定点),始终需要一个时区(或与 UTC的时、分、秒的偏移量)。

\n\n

要通过特定地区(时区)的人们使用的挂钟时间查看同一时刻,请应用 aZoneId来获取ZonedDateTime

\n\n

以、、 或 等格式指定正确的时区名称。切勿使用 2-4 个字母的缩写,例如或或,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。Continent/RegionAmerica/MontrealAfrica/CasablancaPacific/AucklandBSTESTIST

\n\n
ZoneId z = ZoneId.of( "Europe/London" ) ;\nZonedDateTime zdt = instant.atZone( z ) ;  // Same moment, same point on the timeline, different wall-clock time.\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

2019-05-21T12:51:44.711+01:00[欧洲/伦敦]

\n
\n\n

请注意一天中时间的调整,从 11 点到 12 点。这是有道理的,因为Europe/London该日期的时区比 UTC 早一小时。同一时刻,时间轴上的同一点,不同的挂钟时间。

\n\n

捷径

\n\n

正如 Ole VV 在评论中指出的那样,您可以跳过上面讨论的数学。将整个纳秒数作为第二个参数提供给ofEpochSecond。该类在内部进行数学运算,将整秒与小数秒分开。

\n\n
Instant instant = Instant.ofEpochSecond( 0L , 1_558_439_504_711_000_000L ) ;\n
Run Code Online (Sandbox Code Playgroud)\n\n

请参阅在 IdeOne.com 上实时运行的代码。

\n\n

生成文本

\n\n

ZonedDateTime生成表示标准ISO 8601格式的值的文本,该格式扩展为在方括号中附加时区名称。

\n\n
String output = zdt.toString() ;\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

2019-05-21T12:51:44.711+01:00[欧洲/伦敦]

\n
\n\n

或者让java.time自动为您本地化。

\n\n
Locale locale = Locale.UK;\nDateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.SHORT ).withLocale( locale );\nString output = zdt.format( f );\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

21/05/2019, 12:51

\n
\n\n

或者指定自定义格式。

\n\n
Locale locale = Locale.UK;\nDateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MM-uuuu HH:mm:ss" , locale ) ;\nString output = zdt.format( f );\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

21-05-2019 12:51:44

\n
\n\n

提示:在未明确指定区域的情况下提供日期时间时要非常小心。这会产生歧义,用户可能会假设正在使用不同的区域/偏移。

\n