5

我遇到了这样的代码片段:

Timestamp expiryDate = Timestamp.valueOf(dateStr + " " + "23:59:59.000");

这里 dateStr 是用户在表单中输入的字符串,格式为 yyyy-mm-dd。现在 Timestamp.valueOf 的行为是将不存在的日期转换为适当的日期。假设从 2008 年 6 月 31 日到 2008 年 7 月 1 日。

如果 dateStr 字符串实际上是有效日期,我如何检查 Java?我知道我可以手动进行检查,但我想知道是否有任何方法可以做同样的事情。

4

2 回答 2

7

试试SimpleDateFormat。您只需设置一种格式,例如示例中的格式,然后在 dateStr 上调用 parse。

于 2008-10-22T18:20:15.043 回答
1

java.time

java.util日期时间 API 及其格式化 API已SimpleDateFormat过时且容易出错。由于java.sql.Timestampextends java.util.Date,它遇到了同样的问题。建议完全停止使用它们并切换到现代 Date-Time API *

使用java.time现代日期时间 API 的解决方案:DateTimeFormatter您可以使用ResolverStyleas定义一个ResolverStyle.STRICTResolverStyle.SMART默认情况下。

演示:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.format.ResolverStyle;
import java.time.format.SignStyle;
import java.time.temporal.ChronoField;
import java.util.Locale;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtf = 
                new DateTimeFormatterBuilder()
                .appendValue(ChronoField.YEAR, 1, 4, SignStyle.NORMAL)
                .appendLiteral('-')
                .appendValue(ChronoField.MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL)
                .appendLiteral('-')
                .appendValue(ChronoField.DAY_OF_MONTH, 1, 2, SignStyle.NORMAL)
                .appendLiteral(' ')
                .appendValue(ChronoField.HOUR_OF_DAY, 1, 2, SignStyle.NORMAL)
                .appendLiteral(':')
                .appendValue(ChronoField.MINUTE_OF_HOUR, 1, 2, SignStyle.NORMAL)
                .appendLiteral(':')
                .appendValue(ChronoField.SECOND_OF_MINUTE, 1, 2, SignStyle.NORMAL)
                .optionalStart()
                .appendLiteral('.')
                .appendFraction(ChronoField.NANO_OF_SECOND, 0, 3, false)
                .optionalEnd()
                .toFormatter(Locale.ENGLISH)
                .withResolverStyle(ResolverStyle.STRICT);
        
        // Test
        Stream.of(
                "2008-06-31 23:59:59.000",
                "2008-06-30 23:59:59.000",
                "2008-6-30 23:59:59.000",
                "2008-6-8 23:59:59.000",
                "2008-6-8 2:59:59.000",
                "2008-6-8 23:5:59.000",
                "2008-6-8 23:59:9.000",
                "2008-06-30 23:59:59"
                
        ).forEach (s -> {
            try {
                LocalDateTime ldt = LocalDateTime.parse(s, dtf);
                System.out.println(ldt);
            }catch(DateTimeParseException e) {
                System.out.printf("%s is an invalid date-time string.%n", s);
                // ...
            }
        });     
    }
}

输出:

2008-06-31 23:59:59.000 is an invalid date-time string.
2008-06-30T23:59:59
2008-06-30T23:59:59
2008-06-08T23:59:59
2008-06-08T02:59:59
2008-06-08T23:05:59
2008-06-08T23:59:09
2008-06-30T23:59:59

ONLINE DEMO

从Trail: Date Time了解有关现代日期时间 API 的更多信息。检查此答案此答案以了解如何将java.timeAPI 与 JDBC 一起使用。

如果有的话,您需要一个实例java.sql.Timestamp

您可以将 a 转换LocalDateTimejava.sql.Timestamp使用Timestamp#valueOf例如

LocalDateTime now = LocalDateTime.now();
Timestamp ts = Timestamp.valueOf(now);

* 如果您正在为一个 Android 项目工作,并且您的 Android API 级别仍然不符合 Java-8,请通过 desugaring 检查可用的 Java 8+ API。请注意,Android 8.0 Oreo 已经提供java.time.

于 2021-11-08T19:44:02.883 回答