如何在 Json 中发送 java.util.Date?
Posted
技术标签:
【中文标题】如何在 Json 中发送 java.util.Date?【英文标题】:How to send java.util.Date in Json? 【发布时间】:2015-10-25 09:08:08 【问题描述】:我需要在 json 中发送数据。重要的是我希望保留语言环境,以便接收者获得他当地时间的日期。我该怎么做?
我不能简单地使用Date.toString()
,因为如果它们的语言环境不同(不同的日期和月份名称等),我将无法在接收端将其解析回日期。
有解决办法吗?
【问题讨论】:
【参考方案1】:tl;博士
Instant.now()
.toString()
2017-01-23T12:34:56.123456789Z
UTC
通常最好将数据交换为 UTC (GMT) 中的日期时间值。让接收器调整到所需的时区。
Instant
Instant
类代表 UTC 时间轴上的一个时刻,分辨率为纳秒。
Instant instant = Instant.now() ;
String output = instant.toString() ; // Generate a String in standard ISO 8601 format.
2017-01-23T12:34:56.123456789Z
您可以轻松解析该字符串。
Instant instant = Instant.parse( "2017-01-23T12:34:56.123456789Z" ) ;
ISO 8601
ISO 8601 标准为日期时间值的文本表示定义了清晰易读易解析的格式。这些格式非常适合数据交换。
在 UTC 中,这意味着上面示例中看到的格式。 T
将日期部分与时间部分分开。末尾的Z
是Zulu
的缩写,表示UTC。
语言环境
问题提到区域设置,好像与时区有关。 Locale
与时区无关。 Locale
指定 (a) 用于翻译日期名称、月份名称等的人类语言,以及 (b) 决定缩写、大写、标点符号等问题的文化规范。
时区是区域offset-from-UTC 更改的历史记录,跟踪导致这些更改的异常情况,例如Daylight Saving Time (DST)。
搜索 Stack Overflow 以了解更多信息。这已经被覆盖了数百次。搜索 ZoneId
、ZoneOffset
、ZonedDateTime
、Instant
、OffsetDateTime
和 DateTimeFormatter
等类。阅读 java.time 类上的Oracle Tutorial。
ZonedDateTime zdt = instant.atZone( ZoneId.of( "Pacific/Auckland" ) ) ;
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date
、Calendar
和 SimpleDateFormat
。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.*
类。
从哪里获得 java.time 类?
Java SE 8、Java SE 9、Java SE 10、Java SE 11 和更高版本 - 具有捆绑实现的标准 Java API 的一部分。 Java 9 添加了一些小功能和修复。 Java SE 6 和 Java SE 7 大部分 java.time 功能都在 ThreeTen-Backport 中向后移植到 Java 6 和 7。 Android java.time 类的 android 捆绑包实现的更高版本。 对于早期的 Android (ThreeTenABP 项目适应 ThreeTen-Backport(如上所述)。见How to use ThreeTenABP…。ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval
、YearWeek
、YearQuarter
和more。
【讨论】:
【参考方案2】:有很多方法可以做到这一点。 一种以毫秒为单位转换日期的方法,它不依赖于语言环境并进一步使用它。 另一种以 utc 格式更改日期并进一步使用它的方法。如果您的服务器的时区设置为 UTC,java.util.Date 将完美运行,因为在使用 new Date("some date") 时默认采用系统时区。示例:
long lastAccessedDate = 110002028250;
String myDate = new java.util.Date(lastAccessedDate()).toString();
如果系统时区为 UTC,则 myDate 将为“Tue Jun 06 05:30:00 UTC 2017”。
【讨论】:
我必须不同意你的所有观点。对于epoch reference date 和粒度(天、整秒、毫秒、微秒、纳秒),毫秒计数是不明确的。没有“UTC格式”之类的东西。主机操作系统或JVM的默认时区不在程序员的控制范围内,因此不可靠;最好明确指定您的预期/所需时区。麻烦的Date
类使用了一种糟糕的格式,现在已被java.time.Instant
取代。【参考方案3】:
试试这个格式: 2017-03-20T00:00:00.000+0100
【讨论】:
它与其他答案有何不同?【参考方案4】:自 1970 年以来的一毫秒时间是可以的,但不是人类可读的,因此是用于测试/开发的 PITA。
因此使用 ISO 8601 标准日期时间 "yyyy-MM-dd'T'HH:mm:ss"
(其中'T'
只是文字T
(人们经常在这里看到一个空格;还有小数秒.SSS
)。
时间 zone 也是可能的,但希望不需要(= 包含在本地化时间中)。
在 java 8 之前使用SimpleDateFormat
。
【讨论】:
【参考方案5】:我认为有一种简单的方法可以做到这一点,
DateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
yourJsonObject.accumulate("yourDateVarible",dateFormat.format(new Date()));
【讨论】:
【参考方案6】:执行此操作的正确方法是以 ISO 8601 格式编写您的日期:
即2015-08-03T4:50:49+00:00
不仅包含时区,而且 JSON 接收端的任何标准解码器都能够毫无问题地对其进行解码。
对于发送部分,如果您自己编写字符串,那么只需格式化它:
ZonedDateTime.now( ZoneId.systemDefault() )
.format( DateTimeFormatter.ISO_DATE_TIME )
但是,如果您使用任何 JSON 序列化程序从 Java 对象(例如 Jackson)进行转换,那么只需将对象属性设置为 java.util.Date
,并且如果设置正确,则序列化程序应该知道该做什么。有关杰克逊,请参阅this answer,或泽西岛请参阅 this one。他们都使用 Joda Time。
【讨论】:
【参考方案7】:使用 java.util.Date 的 getTime 方法获取时间戳。将其转换回日期后,每个接收者都可以使用其本地时区显示它。
记住那个日期
表示特定的时间瞬间,精度为毫秒。
toString 方法只是将其格式化为specific way:
dow mon dd hh:mm:ss zzz yyyy
选择发送时间戳意味着您还可以使用更少的带宽。
【讨论】:
当日期在一个时区创建并传递到另一个时区并在另一个时区消费时会发生什么? 在时区中创建的日期被转换为自 1970 年 1 月 1 日 00:00:00 GMT 以来的毫秒数(通过 getTime),然后这个数字被转换为任何时区的日期。跨度> 这可能就是我要找的东西。毫秒数是多少? @Greyshack 它很长 :) 与名为“long”的 java 原始数据类型一样。当前毫秒为 1438596711244。它将在相当长的一段时间内保持 14 个字符(以毫秒为单位)。以上是关于如何在 Json 中发送 java.util.Date?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 C# 在 POST 请求中发送 json 数据 [重复]
WCF POST 通过 JQuery。如何在 JSON 中发送数组?
如何在 php 的 HTTP 标头响应中仅发送 JSON 数据?