Timestamp can't be parsed Issue java.time.format.DateTimeParseException: Text '9/25/2020, 12:46:00 PM' could not be parsed at index 0

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

Timestamp can't be parsed Issue java.time.format.DateTimeParseException: Text '9/25/2020, 12:46:00 PM' could not be parsed at index 0

问题

我正试图在检查网页上的时间戳值之前和之后捕获时间,并确认我的时间戳是否在这些时间之间。然而,我在以一种清晰的方式将字符串时间戳转换为可比较的格式方面遇到了困难。

Instant b4 = Instant.now();

// 我的代码提交一个文件,然后触发时间戳。我将其作为字符串检索
// 例如字符串:"9/25/2020, 11:03:18 AM"

DateTimeFormatter dtf = DateTimeFormatter
        .ofPattern("MM/dd/yyyy, HH:mm:ss a")
        .withZone(ZoneId.systemDefault());
Instant instantTimestamp = Instant.from(dtf.parse(timeStamp));

Instant after = Instant.now();          

if (instantTimestamp.isAfter(b4) && instantTimestamp.isBefore(after)) {
    testPass = true;
}

Assert.assertTrue(testPass);

我的错误:
java.time.format.DateTimeParseException: Text '9/25/2020, 12:46:00 PM' 无法在索引 0 处解析

英文:

I am attempting to capture the time before and after I check a timestamp value on a webpage and then confirm my timestamp falls in between those times. However, I'm struggling to convert my String timestamp into a comparable format in a clean way.

        Instant b4 = Instant.now();
                    
        //My code submites a file that then triggers the timestamp. I retrieve it as a string
        //exa string"9/25/2020, 11:03:18 AM"

        DateTimeFormatter dtf = DateTimeFormatter
                .ofPattern("MM/dd/yyyy, HH:mm:ss a")
                .withZone(ZoneId.systemDefault());
        Instant instantTimestamp = Instant.from(dtf.parse(timeStamp));

        Instant after = Instant.now();          

        if (instantTimestamp.isAfter(b4) && instantTimestamp.isBefore(after)) {
            testPass = true;
        }

        Assert.assertTrue(testPass);

My Error:
java.time.format.DateTimeParseException: Text '9/25/2020, 12:46:00 PM' could not be parsed at index 0

答案1

得分: 4

错误是由于使用了错误的格式字符串导致的。"MM" 要求输入字符串的月份部分恰好为两位数字,但是 "9" 只有一个数字。换句话说,它适用于 "09/25/2020, 11:03:18 AM",但不适用于 "9/25/2020, 11:03:18 AM"。

这里需要使用 "M",它不需要在值之前加上 "0":

        DateTimeFormatter dtf = DateTimeFormatter
                .ofPattern("M/dd/yyyy, HH:mm:ss a")
                .withZone(ZoneId.systemDefault());

如果日期也可以是单个数字,对于 0 到 9 号的日期不需要填充为 0,应该使用 "M/d/yyyy, HH:mm:ss a" 模式。

这在 DateTimeFormatter Javadoc 中有描述:

> 所有字母 'A' 到 'Z' 和 'a' 到 'z' 都被保留为模式字母。下面定义了一些模式字母:
>
>none > Symbol Meaning Presentation Examples > ------ ------- ------------ ------- > [...] > M/L 一年中的月份 数字/文本 7; 07; Jul; July; J > [...] >
>
> 文本: [...]
>
> 数字: 如果字母的数量为1,则输出值时使用最小数量的数字,并且不填充。否则,数字的数量被用作输出字段的宽度,并根据需要填充值为零。[...]
>
> 数字/文本: 如果模式字母的数量为3或更多,请使用上面的文本规则。否则使用上面的数字规则。

因为 "M" 使用了 "数字/文本" 表示法,而你的格式("MM")的字母数量是2,因此它需要月份恰好有两位数字。将其改为单个 "M" 会导致它使用最小数量的数字(对于1到9月份使用一位数字,对于10到12月份使用两位数字)。

英文:

The error is due to the format string being used. "MM" requires the month portion of the input string to be exactly two digits long, but "9" is only one digit. In other words, it works for "09/25/2020, 11:03:18 AM", but not for "9/25/2020, 11:03:18 AM".

What's needed here is "M", which doesn't require the value to be preceded by "0":

        DateTimeFormatter dtf = DateTimeFormatter
                .ofPattern("M/dd/yyyy, HH:mm:ss a")
                .withZone(ZoneId.systemDefault());

If the date should also be allowed to be a single digit and not 0-padded for days 0-9, the "M/d/yyyy, HH:mm:ss a" pattern should be used instead.

This is described the DateTimeFormatter Javadocs:

> All letters 'A' to 'Z' and 'a' to 'z' are reserved as pattern letters. The following pattern letters are defined:
>
>none
> Symbol Meaning Presentation Examples
> ------ ------- ------------ -------
> [...]
> M/L month-of-year number/text 7; 07; Jul; July; J
> [...]
>

>
> Text: [...]
>
> Number: If the count of letters is one, then the value is output using the minimum number of digits and without padding. Otherwise, the count of digits is used as the width of the output field, with the value zero-padded as necessary. [...]
>
> Number/Text: If the count of pattern letters is 3 or greater, use the Text rules above. Otherwise use the Number rules above.

Since "M" uses the "number/text" presentation, and the count of its letters your format ("MM") is 2, then it requires exactly two digits for the month. Switching it to a single "M" causes it to use the minimum number of digits (one digit for months 1-9, and two digits for months 10-12).

答案2

得分: 2

格式与字符串中月份及其值不匹配。格式为 MM,指定了两位数的月份,但值为 9,是个位数。您可以使用单个字母表示月份、日期、年份、小时、分钟、秒等,以适应所有允许的位数。此外,我建议您以不区分大小写的方式解析它,以便可以适应大写和小写(例如 AMam)。

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // 给定的日期时间字符串
        String dateTimeString = "9/25/2020, 12:46:00 PM";

        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                                .parseCaseInsensitive()
                                .appendPattern("M/d/u, h:m:s a")
                                .toFormatter(Locale.ENGLISH);

        // 将给定的日期时间字符串转换为 LocalDateTime
        LocalDateTime ldt = LocalDateTime.parse(dateTimeString, dtf);
        System.out.println(ldt);

        // 如果需要,将其转换为 LocalDateTime 的 Instant
        Instant instant = ldt.toInstant(ZoneOffset.UTC);
        System.out.println(instant);
    }
}

输出:

2020-09-25T12:46
2020-09-25T12:46:00Z

如果此日期时间所属的时区与 UTC 不同,请通过 ZonedDateTime 将其转换为 Instant,例如:

Instant instant = ldt.atZone(ZoneId.of("America/Los_Angeles")).toInstant();

Trail: Date Time 了解更多关于现代日期时间 API 的信息。

在线演示

英文:

There is a mismatch in the format for the month and its value in the string. The format is MM which specifies two digits but the value is 9 which is a single digit. You can use single letters for month, day, year, hour, minute, seconds etc. to accommodate all allowable numbers of digits. Also, I suggest you parse it in a case-insensitive way so that upper and lower case (e.g. AM and am) both can be accommodated.

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;

public class Main {
	public static void main(String[] args) {
		// Given date-time string
		String dateTimeString = "9/25/2020, 12:46:00 PM";

		DateTimeFormatter dtf = new DateTimeFormatterBuilder()
								.parseCaseInsensitive()
								.appendPattern("M/d/u, h:m:s a")
								.toFormatter(Locale.ENGLISH);

		// Convert the given date-time string to LocalDateTime
		LocalDateTime ldt = LocalDateTime.parse(dateTimeString, dtf);
		System.out.println(ldt);

		// Convert to LocalDateTime Instant if required
		Instant instant = ldt.toInstant(ZoneOffset.UTC);
		System.out.println(instant);
	}
}

Output:

2020-09-25T12:46
2020-09-25T12:46:00Z

<kbd>ONLINE DEMO</kbd>

If the timezone to which this Date-Time belongs is different from UTC, convert it to Instant through ZonedDateTime e.g.

Instant instant = ldt.atZone(ZoneId.of(&quot;America/Los_Angeles&quot;)).toInstant();

Learn more about the modern Date-Time API from Trail: Date Time.

huangapple
  • 本文由 发表于 2020年9月26日 01:18:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/64068677.html
匿名

发表评论

匿名网友

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

确定