【发布时间】:2015-10-25 09:08:08
【问题描述】:
我需要在 json 中发送数据。重要的是我希望保留语言环境,以便接收者获得他当地时间的日期。我该怎么做?
我不能简单地使用Date.toString(),因为如果它们的语言环境不同(不同的日期和月份名称等),我将无法在接收端将其解析回日期。
有解决办法吗?
【问题讨论】:
标签: java json string http date
我需要在 json 中发送数据。重要的是我希望保留语言环境,以便接收者获得他当地时间的日期。我该怎么做?
我不能简单地使用Date.toString(),因为如果它们的语言环境不同(不同的日期和月份名称等),我将无法在接收端将其解析回日期。
有解决办法吗?
【问题讨论】:
标签: java json string http date
Instant.now()
.toString()
2017-01-23T12:34:56.123456789Z
通常最好将数据交换为 UTC (GMT) 中的日期时间值。让接收器调整到所需的时区。
InstantInstant 类代表 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 标准为日期时间值的文本表示定义了清晰易读易解析的格式。这些格式非常适合数据交换。
在 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 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 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。
【讨论】:
有很多方法可以做到这一点。 一种以毫秒为单位转换日期的方法,它不依赖于语言环境并进一步使用它。 另一种以 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”。
【讨论】:
Date 类使用了一种糟糕的格式,现在已被java.time.Instant 取代。
试试这个格式: 2017-03-20T00:00:00.000+0100
【讨论】:
自 1970 年以来的一毫秒时间是可以的,但不是人类可读的,因此是用于测试/开发的 PITA。
因此使用 ISO 8601 标准日期时间 "yyyy-MM-dd'T'HH:mm:ss"(其中'T' 只是文字T(人们经常在这里看到一个空格;还有小数秒.SSS)。
时间 zone 也是可能的,但希望不需要(= 包含在本地化时间中)。
在 java 8 之前使用SimpleDateFormat。
【讨论】:
我认为有一种简单的方法可以做到这一点,
DateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
yourJsonObject.accumulate("yourDateVarible",dateFormat.format(new Date()));
【讨论】:
执行此操作的正确方法是以 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。
【讨论】:
使用 java.util.Date 的 getTime 方法获取时间戳。将其转换回日期后,每个接收者都可以使用其本地时区显示它。
记住那个日期
表示特定的时间瞬间,精度为毫秒。
toString 方法只是将其格式化为specific way:
dow mon dd hh:mm:ss zzz yyyy
选择发送时间戳意味着您还可以使用更少的带宽。
【讨论】: