将UTC时间字符串转换为日期格式

huangapple go评论177阅读模式
英文:

Convert UTC string date to date format

问题

如何将字符串“2020-09-02T12:22:53.9”转换为Java中的日期格式2020-09-02T12:22:53.9?

String dateString = "2020-09-02T12:22:53.9";
String tz = "America/Mexico_City";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.S");
ZoneId zoneId = ZoneId.of(tz);
Instant instant = Instant.parse(dateString);
ZonedDateTime dateTimeInTz = ZonedDateTime.ofInstant(instant, zoneId);
System.out.println(dateTimeInTz.format(dtf));

此代码会在行 Instant instant = Instant.parse(dateString); 处抛出 java.time.format.DateTimeParseException: Text '2020-09-02T12:22:53.9' could not be parsed at index 21 异常。

英文:

How to convert string "2020-09-02T12:22:53.9" to date format 2020-09-02T12:22:53.9 in java?

String dateString = "2020-09-02T12:22:53.9";
String tz = "America/Mexico_City";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-dd-mm hh:mm:ss.S");
ZoneId zoneId = ZoneId.of(tz);
Instant instant = Instant.parse(dateString);
ZonedDateTime dateTimeInTz =ZonedDateTime.ofInstant(instant, zoneId);
System.out.println(dateTimeInTz.format(dtf));

This code throws a java.time.format.DateTimeParseException: Text '2020-09-02T12:22:53.9' could not be parsed at index 21 form the line Instant instant = Instant.parse(dateString);.

答案1

得分: 2

你的格式不正确。你使用了 mm,而不是 MM 来表示月份。另外,在格式中你漏掉了字面上的 T。请注意,你需要使用 HH 来表示24小时制的时间。

由于你的日期时间字符串没有包含时区信息,你需要首先将日期时间字符串解析为 LocalDateTime,然后使用 LocalDateTime#atZone 将其转换为 ZonedDateTime(如果你确实需要 ZonedDateTime),示例如下:

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String dateString = "2020-09-02T12:22:53.9";

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-dd-MM'T'HH:mm:ss.S");

        String tz = "America/Mexico_City";
        ZoneId zoneId = ZoneId.of(tz);

        // 解析给定的日期时间字符串为 LocalDateTime
        LocalDateTime ldt = LocalDateTime.parse(dateString, dtf);

        // 将 LocalDateTime 转换为 ZonedDateTime
        ZonedDateTime dateTimeInTz = ldt.atZone(zoneId);

        // 以默认格式显示 ZonedDateTime
        System.out.println(dateTimeInTz);

        // 以自定义格式显示 ZonedDateTime
        System.out.println(dateTimeInTz.format(dtf));
    }
}

输出:

2020-02-09T12:22:53.900-06:00[America/Mexico_City]
2020-09-02T12:22:53.9

或者,你可以直接将 ZoneIdDateTimeFormatter 结合使用,然后可以直接将给定的日期时间字符串解析为 ZonedDateTime,示例如下:

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String dateString = "2020-09-02T12:22:53.9";

        String tz = "America/Mexico_City";
        ZoneId zoneId = ZoneId.of(tz);

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-dd-MM'T'HH:mm:ss.S").withZone(ZoneId.of(tz));

        // 将给定的日期时间字符串解析为 ZonedDateTime
        ZonedDateTime dateTimeInTz = ZonedDateTime.parse(dateString, dtf);

        // 以默认格式显示 ZonedDateTime
        System.out.println(dateTimeInTz);

        // 以自定义格式显示 ZonedDateTime
        System.out.println(dateTimeInTz.format(dtf));
    }
}

输出:

2020-02-09T12:22:53.900-06:00[America/Mexico_City]
2020-09-02T12:22:53.9
英文:

Your format is not correct. You have used mm, instead of MM, for the month. Also, you have missed the literal T in the format. Note that you need to use HH for 24-hours format time.

Since your date-time string does not have a time-zone information, you will have to parse the date-time string to LocalDateTime and then use LocalDateTime#atZone to convert it to ZonedDateTime (if at all you need ZonedDateTime) as shown below:

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
	public static void main(String[] args) {
		String dateString = "2020-09-02T12:22:53.9";

		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-dd-MM'T'HH:mm:ss.S");

		String tz = "America/Mexico_City";
		ZoneId zoneId = ZoneId.of(tz);

		// Parse the given date-time string to LocalDateTime
		LocalDateTime ldt = LocalDateTime.parse(dateString, dtf);

		// Convert the LocalDateTime to ZonedDateTime
		ZonedDateTime dateTimeInTz = ldt.atZone(zoneId);

		// Display ZonedDateTime in its default format
		System.out.println(dateTimeInTz);

		// Display ZonedDateTime in your custom format
		System.out.println(dateTimeInTz.format(dtf));
	}
}

Output:

2020-02-09T12:22:53.900-06:00[America/Mexico_City]
2020-09-02T12:22:53.9

Alternatively, you can use the ZoneId with DateTimeFormatter itself and then you can parse the given date-time string directly into ZonedDateTime as shown below:

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
	public static void main(String[] args) {
		String dateString = "2020-09-02T12:22:53.9";

		String tz = "America/Mexico_City";
		ZoneId zoneId = ZoneId.of(tz);

		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-dd-MM'T'HH:mm:ss.S").withZone(ZoneId.of(tz));

		// Parse the given date-time string into ZonedDateTime
		ZonedDateTime dateTimeInTz = ZonedDateTime.parse(dateString, dtf);

		// Display ZonedDateTime in its default format
		System.out.println(dateTimeInTz);

		// Display ZonedDateTime in your custom format
		System.out.println(dateTimeInTz.format(dtf));
	}
}

Output:

2020-02-09T12:22:53.900-06:00[America/Mexico_City]
2020-09-02T12:22:53.9

答案2

得分: 1

// 代码部分不要翻译

I take it that your date string is in America/Mexico_City time zone and that you want output in the same time zone, so the same date and time. I further take it that internally in your program you want to represent the point in time as an `Instant`. The full circle from your date string to `Instant` and back may go:

String tz = "America/Mexico_City";
ZoneId zoneId = ZoneId.of(tz);

String dateString = "2020-09-02T12:22:53.9";

Instant instant = LocalDateTime.parse(dateString).atZone(zoneId).toInstant();
System.out.println(instant);

ZonedDateTime dateTimeInTz =ZonedDateTime.ofInstant(instant, zoneId);
System.out.println(dateTimeInTz.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));

Output:

>     2020-09-02T17:22:53.900Z
>     2020-09-02T12:22:53.9

Your input and your identical output are in ISO 8601 format. `LocalDateTime` parses ISO 8601 format without time zone or offset as its default, that is, without any explicit formatter. For printing the `ZonedDateTime` back in the same format, we are using the built-in `DateTimeFormatter.ISO_LOCAL_DATE_TIME`. As you may have realized by now, being free from specifying our own format pattern string is a great relief.

## What went wrong in your code?

Arvind Kumar Avinash has already reported the errors in your format pattern string. More fundamentally, you cannot parse your string into an `Instant`, or more precisely, it takes something more to do that. The reason is that Java and the `Instant` class dont know and cannot guess which time zone you intended. Your date string has date and time of day without any time zone. An `Instant` is a point in time, conceptually without any date or time of day. Your string could represent different points in time in different time zones, so only by specifying the time zone is it possible to determine the point in time.

What the `Instant` class *can* parse is a date and time *in UTC* denoted by a `Z`. An example of such a string is in the output from the `Instant` above, `2020-09-02T17:22:53.900Z`. Since your string is not in UTC (and therefore hasnt got the `Z`), this observation doesnt help us in your case.

## Link

 - [Wikipedia article: ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)
英文:

No formatter needed

I take it that your date string is in America/Mexico_City time zone and that you want output in the same time zone, so the same date and time. I further take it that internally in your program you want to represent the point in time as an Instant. The full circle from your date string to Instant and back may go:

	String tz = "America/Mexico_City";
ZoneId zoneId = ZoneId.of(tz);
String dateString = "2020-09-02T12:22:53.9";
Instant instant = LocalDateTime.parse(dateString).atZone(zoneId).toInstant();
System.out.println(instant);
ZonedDateTime dateTimeInTz =ZonedDateTime.ofInstant(instant, zoneId);
System.out.println(dateTimeInTz.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));

Output:

> 2020-09-02T17:22:53.900Z
> 2020-09-02T12:22:53.9

Your input and your identical output are in ISO 8601 format. LocalDateTime parses ISO 8601 format without time zone or offset as its default, that is, without any explicit formatter. For printing the ZonedDateTime back in the same format, we are using the built-in DateTimeFormatter.ISO_LOCAL_DATE_TIME. As you may have realized by now, being free from specifying our own format pattern string is a great relief.

What went wrong in your code?

Arvind Kumar Avinash has already reported the errors in your format pattern string. More fundamentally, you cannot parse your string into an Instant, or more precisely, it takes something more to do that. The reason is that Java and the Instant class don’t know and cannot guess which time zone you intended. Your date string has date and time of day without any time zone. An Instant is a point in time, conceptually without any date or time of day. Your string could represent different points in time in different time zones, so only by specifying the time zone is it possible to determine the point in time.

What the Instant class can parse is a date and time in UTC denoted by a Z. An example of such a string is in the output from the Instant above, 2020-09-02T17:22:53.900Z. Since your string is not in UTC (and therefore hasn’t got the Z), this observation doesn’t help us in your case.

huangapple
  • 本文由 发表于 2020年9月25日 04:04:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/64053655.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定