转换JSON日期格式
我收到一个日期值如下的JSON对象:
{"PostingDate":"\/Date(1325134800000-0500)\/"}
我想用Java代码解析它到Date
或将它作为String
。
我想知道做这件事的简单方法是什么。
我认为第一个数字( 1325134800000
)是自纪元以来的毫秒数, -0500
是时区。 这似乎是下面的示例代码的情况,这似乎做你想要的。
以下代码使用Jackson解析JSON输入,如果您还没有选择JSON解析库,我建议使用它。 它缺乏错误检查等。
示例代码:
public final class Foo { public static void main(final String... args) throws IOException { // What the JSON value must match exactly // Not anchored since it will be used with the (misnamed) .matches() method final Pattern pattern = Pattern.compile("\\\\/Date\\((\\d+)(-\\d+)?\\)\\\\/"); final ObjectMapper mapper = new ObjectMapper(); // Parse JSON... final JsonNode node = mapper.readTree( "{\"PostingDate\": \"\\/Date(1325134800000-0500)\\/\"}"); if (!node.has("PostingDate")) { System.err.println("Bad JSON input!"); System.exit(1); } // Get relevant field final String dateSpec = node.get("PostingDate").getTextValue(); // Try and match the input. final Matcher matcher = pattern.matcher(dateSpec); if (!matcher.matches()) { System.err.println("Bad pattern!"); // Yuck System.exit(1); } // The first group capture the milliseconds, the second one the time zone final long millis = Long.parseLong(matcher.group(1)); String tz = matcher.group(2); if (tz.isEmpty()) // It can happen, in which case the default is assumed to be... tz = "+0000"; // Instantiate a date object... final Date date = new Date(millis); // And print it using an appropriate date format System.out.printf("Date: %s %s\n", new SimpleDateFormat("yyyy/MM/dd HH:MM:ss").format(date), tz); } }
输出:
Date: 2011/12/29 06:12:00 -0500
Hier是一种基于fge版本的工作解析方法,但改进为
- 它使用了jode的DateTime,并初始化了正确的时区
- 模式的微小变化也接受+0200
=>
private static final Pattern bingTimePattern = Pattern.compile("\\/Date\\((\\d+)([-+]\\d+)?\\)\\/"); public static DateTime parseBingTime(String timeAsString) throws ParseException { Matcher matcher = bingTimePattern.matcher(timeAsString); if (!matcher.find()) throw new ParseException("wrong date time format " + timeAsString, 0); final long millis = Long.parseLong(matcher.group(1)); String tz = matcher.group(2); if (tz.isEmpty()) tz = "+0000"; return new DateTime(millis, DateTimeZone.forID(tz)); }
我使用Jquery DatePicker创建了一个简单的JavaScript函数
function JsonToJSDate(jsonDate) { var reg = /-?\d+/; var m = reg.exec(jsonDate); return new Date(parseInt(m[0])); }
$(’#Started’)。val($。datepicker.formatDate(’mm / dd / yy’,JsonToJSDate(yourDateVarHere)));
简单的事情,但处理我的工作。 从JSON中提取对象值并应用子字符串。
例如:
String postingDateObjectValue = "\\/Date(1442436473422)\\/"; String dateStringInMillis = postingDateObjectValue .substring(7,20);
现在解析millis并在任何你想要的地方使用它们。
在Java> = 8中,您可以使用新的java.time
API 。
输入包含:
- 一个unix时间戳 (
1325134800000
),这是自unix epoch(1970-01-01T00:00Z
)以来的毫秒数 - UTC偏移量 (
-0500
),这是与UTC的差异(在这种情况下,比UTC晚5小时)
在新的java.time
API中,有许多不同类型的日期/时间对象。 在这种情况下,我们可以选择使用java.time.Instant
(表示自unix epoch以来的纳秒数)或java.time.OffsetDateTime
(表示Instant
转换为特定偏移中的日期/时间)。
为了解析String
,我使用java.time.format.DateTimeFormatterBuilder
来创建java.time.format.DateTimeFormatter
。 我还使用java.time.temporal.ChronoField
来指定我正在解析的字段:
DateTimeFormatter fmt = new DateTimeFormatterBuilder() // epoch seconds .appendValue(ChronoField.INSTANT_SECONDS) // milliseconds .appendValue(ChronoField.MILLI_OF_SECOND, 3) // offset .appendPattern("xx") // create formatter .toFormatter();
我还使用正则表达式从输入String
提取相关部分(尽管您也可以使用substring()
来获取它):
String s = "/Date(1325134800000-0500)/"; // get just the "1325134800000-0500" part - you can also do s.substring(6, 24) s = s.replaceAll(".*/Date\\(([\\d\\+\\-]+)\\)/.*", "$1");
然后我可以解析我想要的类型:
// parse to Instant Instant instant = Instant.from(fmt.parse(s)); // parse to OffsetDateTime OffsetDateTime odt = OffsetDateTime.parse(s, fmt);
Instant
相当于2011-12-29T05:00:00Z
( Instant
只是时间轴中的一个点,你可以认为它始终是UTC)。 OffsetDateTime
具有相同的瞬间,但转换为-0500
偏移量,因此其值为2011-12-29T00:00-05:00
。 但Instant
和OffsetDateTime
代表相同的时间点。
要转换为java.util.Date
,请使用Instant
:
// convert to java.util.Date Date date = Date.from(instant); // if you have an OffsetDateTime, you can do this: Date date = Date.from(odt.toInstant());
那是因为java.util.Date
没有时区/偏移信息 ,它只是表示自unix epoch(与Instant
相同的概念)以来的毫秒数,因此可以很容易地从Instant
转换。
Java 6和7
对于Java 6和7,您可以使用ThreeTen Backport ,这是Java 8的新日期/时间类的一个很好的后端 。 而对于Android ,你还需要ThreeTenABP (更多关于如何在这里使用它)。
与Java 8的区别在于包名(在Java 8中是java.time
,在ThreeTen Backport(或Android的ThreeTenABP中)是org.threeten.bp
),但类和方法名称是相同的。 因此,格式化程序创建和Instant
和OffsetDateTime
的解析代码是相同的。
另一个区别是,在Java <= 7中, java.util.Date
类没有from()
方法。 但您可以使用org.threeten.bp.DateTimeUtils
类进行转换:
// convert to java.util.Date Date date = DateTimeUtils.toDate(instant); // or from the OffsetDateTime Date date = DateTimeUtils.toDate(odt.toInstant());