【问题标题】:Java Date Format that allows - / or . as separators within dateJava 日期格式,允许 - / 或 .作为日期内的分隔符
【发布时间】:2010-11-29 10:18:21
【问题描述】:

解析可以采用以下格式之一的日期的最佳方法是什么

 "dd-MM-yyyy HH:mm"
 "dd/MM/yyyy HH:mm"
 "dd.MM.yyyy HH:mm"

无需创建 3 个 SimpleDateFormat 并针对每个进行解析。

谢谢

【问题讨论】:

    标签: java simpledateformat date-format java-time datetime-parsing


    【解决方案1】:

    java.time

    您可以使用DateTimeFormatter 来实现,它允许您使用方括号指定可选内容。

    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Locale;
    import java.util.stream.Stream;
    
    public class Main {
        public static void main(String args[]) {
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("d[-][.][/]M[-][.][/]u H:m", Locale.ENGLISH);
    
            // Test
            Stream.of(
                        "28-04-2021 14:01", 
                        "28.04.2021 14:01", 
                        "28/04/2021 14:01"
            ).forEach(s -> System.out.println(LocalDateTime.parse(s, dtf)));
        }
    }
    

    输出:

    2021-04-28T14:01
    2021-04-28T14:01
    2021-04-28T14:01
    

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

    请注意,旧的日期时间 API(java.util 日期时间类型及其格式化 API,SimpleDateFormat)已过时且容易出错。建议完全停止使用它们并切换到java.timemodern date-time API*


    * 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7 . 如果您正在为一个 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

    【讨论】:

      【解决方案2】:

      正则表达式怎么样:

      "\\d\\d[./-]\\d\\d[./-]\\d\\d\\d\\d \\d\\d:\\d\\d"
      

      在代码中,这意味着如下:

      Pattern pattern = 
      Pattern.compile("(\\d\\d)([./-])(\\d\\d)([./-])(\\d\\d\\d\\d) (\\d\\d):(\\d\\d)");
      
      Matcher matcher = 
      pattern.matcher("31-07-1983 15:30");
      
      if (matcher.find() && matcher.group(2).equals(matcher.group(4))) {
        int day = Integer.parseInt(matcher.group(1));
        int month = Integer.parseInt(matcher.group(3));
        int year = Integer.parseInt(matcher.group(5));
        int hour = Integer.parseInt(matcher.group(6));
        int minute = Integer.parseInt(matcher.group(7));
      } 
      

      【讨论】:

      • 因为 \ 是 Java 字符串文字中的转义字符,所以您必须将每个 \ 加倍:"\\d\\d[\\.\\/\\-]\\d\ \d[\\.\\/\\-]\\d\\d\\d\\d \\d\\d:\\d\\d"
      • 你错了——你仍然需要在你的Java源代码中写“\\d”,不管这是否是一个正则表达式。
      • 现在我必须去检查一下,先生,您完全正确。这太丑了,他们可以很容易地使用另一个转义字符。
      【解决方案3】:

      用正则表达式自己做:

      public class SpecialDateFormat
      {
          private final static Pattern PATTERN = Pattern.compile("(\\d{2})[\\.\\/\\-](\\d{2})[\\.\\/\\-](\\d{4}) (\\d{2}):(\\d{2})");
      
          public static Date parse(String text) throws ParseException {
              Matcher m = PATTERN.matcher(text);
              if (m.matches()) {
                  int dd = Integer.parseInt(m.group(1));
                  int mm = Integer.parseInt(m.group(2));
                  int yy = Integer.parseInt(m.group(3));
                  int hh = Integer.parseInt(m.group(4));
                  int mi = Integer.parseInt(m.group(5));
      
                  // NOTE: Checking if values are in valid ranges omitted
      
                  Calendar cal = Calendar.getInstance();
                  cal.set(yy, mm - 1, dd, hh, mi, 0);
      
                  return cal.getTime();
              }
              else {
                  throw new ParseException("Unparseable date: " + text, 0);
              }
          }
      }
      

      但是请注意,这确实允许混合不同的分隔符,例如将允许“17-09/2009 12:00”。

      【讨论】:

      • 我称之为公然窃取概念 ;-),你会发现我已经在不同的分隔符检查中付出了很多努力。
      • 显然您不需要转义 [] 之间的任何字符,甚至不需要转义句点。
      【解决方案4】:

      您可以使用Apache commons lang DateUtils.parseDate

      import java.text.ParseException;
      import org.apache.commons.lang.time.DateUtils;
      
      public class Test {
      
      public static void main(String[] args) throws ParseException {
      
          String[] values = new String[]{"31-12-2009 12:00", "31/12/2009 12:00", "31.12.2009 12:00"};
          String[] parsePatterns = new String[]{"dd-MM-yyyy HH:mm", "dd/MM/yyyy HH:mm", "dd.MM.yyyy HH:mm"};
      
          for (String value : values) {
              System.out.println(DateUtils.parseDate(value, parsePatterns));
          }
      }
      }
      

      嗯,它在内部创建了 SimpleDateFormats,但这有什么问题?

      【讨论】:

        【解决方案5】:

        ParseExact 可以采用一系列格式。您仍然需要指定所有格式,但这是一个操作。

        【讨论】:

        • 这是一个 Java 问题,没有 parseExact 方法
        • 这不是 SimpleDateFormat 的方法,也不是 Java 方法的标准情况。你是在引用 C# 还是类似的?
        • 对不起,我的错误。是的,那是 C#。
        【解决方案6】:

        将源字符串“调整”为规范格式可能是最简单的:

        if (text.length() == 16)
        {
            if ((text.charAt(2) == '/' && text.charAt(5) == '/') ||
                (text.charAt(2) == '.' && text.charAt(5) == '.'))
            {
                text = text.substring(0, 2) + "-" + text.substring(3, 5) 
                   + "-" + text.substring(6);
            }
        }
        

        然后使用格式字符串使用“-”。

        请注意,这是非常具体的,只替换完全您感兴趣的字符,以避免不必要的副作用。

        【讨论】:

        • 谢谢,我将开始为我们的代码库开发通用日期解析器,这将是一个好的开始
        【解决方案7】:

        您能否先运行两次替换操作,从而将所有三种格式都简化为一种格式?

        【讨论】:

        • 啊.. 在发布我的答案 +1 之前我没有看到这个。太棒了!
        猜你喜欢
        • 1970-01-01
        • 2018-02-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多