Java 简单的日期格式 - dd/MM/yy v/s dd/MM/yyyy

Java Simple date format - dd/MM/yy v/s dd/MM/yyyy

我需要将 String 解析为 dd/MM/YY hh:mm:ss 格式。

假设如果 String 的值为 09/06/17 05:59:59 那么它应该被解析但是如果 String 的值为 09/06/2017 05:59:59 那么这也是一个有效的格式并且正在被解析但在我的要求中,后面应该抛出解析异常。

代码:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateDemo {

    public static void main(String[] args) {

        String line=" 09/06/17 05:59:59 20170609IT36701706080107 42 103 Output USD 970.20 IT3670";
        //String line=" 09/06/2017 05:59:59 20170609IT36701706080107 42 103 Output USD 970.20 IT3670";

        String dt=null;
        dt=line.substring(1, 19);

        SimpleDateFormat org_format = new SimpleDateFormat("dd/MM/YY hh:mm:ss");
        SimpleDateFormat tgt_format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        try {
              dt=line.substring(1, 19);

              System.out.println(dt);
              Date date = org_format.parse(dt);
              System.out.println(date);

              String tgt_date=tgt_format.format(date);
              System.out.println(tgt_date);
         } catch (ParseException e) {
              System.out.println(line);
         }
    }
}

问题 - 在代码中,未注释的行变量和注释的行变量都成功给出了结果。但是注释行应该抛出可解析的异常,因为它是模式 dd/MM/yyyy,而不是 dd/MM/yy.

fmt.setLenient(false) 不工作。

我正在使用 Java 7。没有使用 Java 8 或更高版本的选项,因此不能使用 java.time

您可以使用正则表达式检查年份是否包含 4 位数字,如果是则抛出新的 ParseException。程序是:

public static void main(String[] args) throws ParseException {

        String date = "09/06/17 05:59:59";

        if (date.matches("\d{1,2}[/.-]\d{1,2}[/.-]\d{4} .*"))
            throw new ParseException("date has wrong format");
        else {

        }

    }

匹配任何这些日期格式的正则表达式

String regex = "^(([0]?[1-9]|1[0-2])/([0-2]?[0-9]|3[0-1])/[1-2]\d{3}) (20|21|22|23|[0-1]?\d{1}):([0-5]?\d{1})$";
Pattern pattern = Pattern.compile(regex);

Matcher matcher = pattern.matcher("09/06/17 05:59:59");

if(matcher.matches()){
    //your next code
}

Don't have option to use java 8 or later so cant use java.time

Java 8 日期和时间 类 已被移植到 Java 6 和 7,所以是的,您可以在 Java 7 中使用它们。获取ThreeTen Backport。这也是面向未来的投资:如果您最终升级到 Java 8 或 9,您只需修改 import 声明,您的代码将与 java.time 类.

所以我建议你把过时的 类 SimpleDateFormatDate 丢在肩上。 SimpleDateFormat 在你想要异常的情况下给你一个结果(通常是不正确的)是非常典型的。正如您所指出的,有时 org_format.setLenient(false); 会有所帮助,但对您而言并非如此。

使用 ThreeTen 反向移植:

    DateTimeFormatter originalFormat = DateTimeFormatter.ofPattern("dd/MM/uu HH:mm:ss");
    ParsePosition pos = new ParsePosition(1); // skip leading space
    LocalDateTime ldt = LocalDateTime.from(originalFormat.parse(line, pos));

这会将您使用两位数年份的行解析为

2017-01-02 05:59:59

对于“在我的要求中,应该抛出解析异常”的4位年份的行,我们得到

Exception in thread "main" java.time.format.DateTimeParseException: Text ' 09/06/2017 05:59:59 20170609IT36701706080107 42 103 Output USD ...' could not be parsed at index 9

它说索引 9,在 2017 中的 17 处,也就是说,正好是年份的第三位数字,当时应该只有两位数字。

需要注意的几点:

  • 在一天中的小时格式模式中使用大写 HH(小写 hh 表示上午或下午的小时,仅对 AM/PM marler 有用)。年份使用小写 uuyy(不是大写 YY,它用于基于周的年份,仅对周数有用)。顺便说一句,再次 SimpleDateFormat 让您摆脱这些错误,并且 有时会给您不正确的结果;现代 类 将通过抛出异常来反对。
  • 我的代码将解析为从 2000 年到 2099 年的年份。请检查这是否是您想要的。您可能想要施加额外的限制,例如,日期时间应该是过去的并且不超过 5 年前,以增强验证。你比我清楚

要转换成您的目标格式:

    DateTimeFormatter targetFormat = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
    String targetDate = ldt.format(targetFormat);

你前面几行的结果是

2017-01-02 05:59:59