【问题标题】:How to resolve Unparseable date Exception in Java 8 with Date format yyyy-MM-dd hh:mm a如何使用日期格式 yyyy-MM-dd hh:mm a 在 Java 8 中解决不可解析的日期异常
【发布时间】:2020-11-01 17:11:00
【问题描述】:

我有一个文本文件,我正在从中读取和设置事务 POJO 类数据,为了获取开始时间和结束时间之间的差异,我需要解析日期对象中的时间信息。

DateFormat format = new SimpleDateFormat(dateFormat);
System.out.println("Date format in play:"+dateFormat);
Transaction transaction = storageRepositroy.getTransaction(key);
Date start = format.parse(transaction.getStartDate() + " " + transaction.getStartTime());//line no. 29
Date end = format.parse(transaction.getEndDate() + " " + transaction.getEndTime());

运行此代码时出现异常

例外是

Date format in play:yyyy-MM-dd hh:mm a
java.text.ParseException: Unparseable date: "2020–03–01 03:15 PM"
    at java.text.DateFormat.parse(DateFormat.java:366)
    at dc.tech.transaction.util.TimeUtil.calculateAverageTime(TimeUtil.java:29)

yyyy-MM-dd hh:mm a 是我传递给 SimleDateFormat 构造函数的日期格式。我无法理解和调试为什么会收到此错误。

【问题讨论】:

  • 我建议你不要使用SimpleDateFormatDate。这些类设计不佳且早已过时,尤其是前者,尤其是出了名的麻烦。而是使用来自java.time, the modern Java date and time APILocalDateTimeDateTimeFormatter
  • 如果您手动键入连字符以测试您的代码是否有效,您的文件中存在连字符问题
  • 都是其他字符。 hyphen 应该有 ascii 45 但你的角色给出 ascii 8211. hyphen in 2020–03–01 。仅在此处注意 - 和 -
  • 快速而肮脏的方法是使用“yyyy–MM–dd hh:mm a”作为dateFormat,因为您的数据本身具有连字符作为–
  • 我没有投反对票(相反)。您的代码示例不完整/不完整,您可以通过providing one that is 改进您的问题。不过,@Ajeetkumar 能够发现问题所在已经足够了。

标签: java date simpledateformat


【解决方案1】:

java.time

我建议您使用现代 Java 日期和时间 API java.time 进行日期和时间工作。

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("uuuu\u2013MM\u2013dd");
    DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mm a", Locale.ENGLISH);
    
    String dateString = "2020–03–01";
    String timeString = "03:15 PM";
    
    LocalDate date = LocalDate.parse(dateString, dateFormatter);
    LocalTime time = LocalTime.parse(timeString, timeFormatter);
    LocalDateTime dateTime = date.atTime(time);
    
    System.out.println(dateTime);

输出:

2020-03-01T15:15

使用 java.time 可以直接在解析后组合日期和时间,因此我更喜欢单独解析它们。

你的代码出了什么问题?

感谢 Ajeetkumar 在 cmets 中的注意和报告:您的日期字符串中的连字符不是通常的减号或字符值 2D 十六进制(十进制 45)的连字符,而是带有 en dash字符值 2013 十六进制(8211 十进制)。因此,当您在格式模式字符串中指定常用连字符时,它们不匹配,并且解析失败。相反,我使用 Unicode 转义将破折号放入格式模式字符串中。只需将其粘贴到那里也可以(前提是您使用支持它的字符编码保存 .java 文件),但我想让读者知道这里发生了一些特别的事情,所以我更喜欢使用 Unicode 转义\u.

您的代码还有另一个问题:您没有为格式化程序提供任何语言环境。因此它使用 JVM 的默认语言环境。只要该语言环境需要PM,解析就可以工作。如果有一天您更改了语言环境设置或在具有不同默认语言环境的计算机或 JVM 上运行代码,解析将突然失败,您可能很难找出原因。我已经指定了英语语言环境来解析时间。有些人也更愿意在约会时这样做,即使从技术上讲这不是必需的。

链接

【讨论】:

    【解决方案2】:

    我始终坚持以下原则:使用与您的日期时间字符串完全相同的格式。

    在下面给出的解决方案中,我已将您的日期时间字符串复制到我为 SimpleDateFormatDateTimeFormatter 指定的模式中,并将数字替换为相应的字母,例如2020yyyy,同时保持其余部分(符号、空格等)完好无损。

    import java.text.DateFormat;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) throws ParseException {
            DateFormat sdf = new SimpleDateFormat("yyyy–MM–dd hh:mm a", Locale.ENGLISH);// Make sure to use Locale
            String dateTimeString = "2020–03–01 03:15 PM";// The string copied from the exception you have got
            Date date = sdf.parse(dateTimeString);
            System.out.println(sdf.format(date));
        }
    }
    

    输出:

    2020–03–01 03:15 PM
    

    注意:java.util 的日期时间 API 及其格式 API SimpleDateFormat 已过时且容易出错。我建议你应该完全停止使用它们并切换到modern date-time API

    使用现代日期时间 API:

    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy–MM–dd hh:mm a", Locale.ENGLISH);// Make sure to use Locale
            String dateTimeString = "2020–03–01 03:15 PM";// The string copied from the exception you have got
            System.out.println(LocalDateTime.parse(dateTimeString, dtf));
        }
    }
    

    输出:

    2020-03-01T15:15
    

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

    如果您正在为您的 Android 项目执行此操作,并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多