zoukankan      html  css  js  c++  java
  • 四、如何科学地在Java开发中——尽可能地自动解析转换各种时间格式的时间字符串为LocalDate?

    需求

    工具类,满足尽可能地自动解析转换各种时间格式的时间字符串为LocalDate,目前支持转换的时间格式有如下,时间字符串至少含有“yyyy”:

    • "yyyy"
    • "yyyy/MM"
    • "yyyy-MM"
    • "yyyy/MM/dd"
    • "yyyy-MM-dd"
    • "yyyy/MM/dd HH:mm"
    • "yyyy-MM-dd HH:mm"
    • "yyyy-MM-dd HH:mm:ss"

    核心全部代码 复制到编译器可以直接运行 更多格式自己改造下

    package test.date;
    
    import lombok.SneakyThrows;
    import lombok.extern.slf4j.Slf4j;
    
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.regex.Pattern;
    
    /**
     * @description 全自动适配各种时间格式的字符串  必须包含年
     * @Date 2020/8/16 23:10
     */
    @Slf4j
    public class AutoDateUtils {
    
        public static final String FORMAT_DATETIME = "yyyy-MM-dd HH:mm:ss";
        public static final String FORMAT = "yyyy-MM-dd";
        public static final String FORMAT2 = "yyyy/MM/dd";
        public static final String FORMAT3 = "yyyy-MM-dd HH:mm";
        public static final String FORMAT5 = "yyyy/MM/dd HH:mm";
    //    public static final String FORMAT6 = "yyyyMMdd";    # 暂不支持
    //    public static final String FORMAT7 = "yyyy年MM月dd日 HH:mm:ss";  # 暂不支持
        public static final String FORMAT8 = "yyyy-MM";
    //    public static final String FORMAT9 = "MM-dd";  # 暂不支持
        public static final String FORMAT10 = "yyyy";
        public static final String FORMAT11 = "yyyy/MM";
    
    
    
        /**
         * 自动适配字符串的配置格式
         */
        private static final List<String> FORMATTERS = Arrays.asList(FORMAT_DATETIME, FORMAT, FORMAT2, FORMAT3, FORMAT5, FORMAT8, FORMAT10, FORMAT11);
        private static Map<String, String> DAY_FORMATTER_MAPS = preParseLocalDate();
    
        // 预处理
        private static Map<String, String> preParseLocalDate() {
    
            Map<String, String> regexMap = new HashMap<>(FORMATTERS.size());
            // 最全的yyyy-MM-dd HH:mm:ss
            for (String format : FORMATTERS) {
                String regex = format.replace("yyyy", "\d{4}").replace("MM", "\d{2}").replace("dd", "\d{2}").replace("HH", "\d{2}").replace("mm", "\d{2}").replace("ss", "\d{2}");
                regexMap.put(format, regex);
            }
            return regexMap;
        }
    
        /**
         * 校验是否为localDate的任意一种格式
         *
         * @param timeText
         * @return
         */
        public static boolean judgeLocalDateFormat(String timeText) {
            for (String formatter : FORMATTERS) {
                String regex = DAY_FORMATTER_MAPS.get(formatter);
                if (Pattern.matches(regex, timeText)) {
                    return true;
                }
            }
            return false;
        }
    
        /**
         * 自动适配字符串, 转换日期字符串为LocalDate
         *
         * @param timeText
         * @return
         */
        public static LocalDate autoParseLocalDate(String timeText) {
            for (String formatter : FORMATTERS) {
                String regex = DAY_FORMATTER_MAPS.get(formatter);
                if (Pattern.matches(regex, timeText)) {
                    // 特殊考虑
                    if (formatter.equals(FORMAT10)) {
                        timeText = timeText.trim() + "-01-01";
                        formatter = FORMAT;
                    } else if (formatter.equals(FORMAT11)) {
                        timeText = timeText.trim() + "/01";
                        formatter = FORMAT2;
                    } else if (formatter.equals(FORMAT8)) {
                        timeText = timeText.trim() + "-01";
                        formatter = FORMAT;
                    }
    //
                    return LocalDate.parse(timeText, DateTimeFormatter.ofPattern(formatter));
    
    //              转为 LocalDateTime 格式, 直接反注释下面这一行并且将上面的 特殊考虑重新修订一遍
    //              return LocalDateTime.parse(timeText, DateTimeFormatter.ofPattern(formatter));
                }
            }
            String msg = timeText + "没有合适的对应的formatter, 请先在DateUtil.DAY_FORMATTER_MAPS 中进行配置";
            log.error(msg);
            throw new RuntimeException(msg);
        }
    
        /**
         * 简单匹配转换yyyyMMdd类型的日期字符串,更多格式自己配置
         *
         * @param timeText
         * @return
         */
        public static String simpleParseStrOfYYYYMMHH(String timeText) throws Exception {
            List<String> regexs = Arrays.asList("\d{4}[-]\d{2}[-]\d{2}", "\d{4}[/]\d{2}[/]\d{2}");
            List<String> formats = Arrays.asList("yyyy-MM-dd", "yyyy/MM/dd");
    
            for (int idx = 0; idx < regexs.size(); idx++) {
                if (Pattern.matches(regexs.get(idx), timeText)) {
                    try {
                        LocalDate parse = LocalDate.parse(timeText, DateTimeFormatter.ofPattern(formats.get(idx)));
                        return parse.toString();
                    } catch (Exception e) {
                        throw new Exception("日期格式错误,请填写正确的日期");
                    }
                }
            }
            throw new Exception("日期格式异常,建议日期格式类型应该为 "yyyy-MM-dd"");
        }
    
    
        @SneakyThrows
        public static void main(String[] args) {
            System.out.println(DAY_FORMATTER_MAPS);
            // 支持8种格式的时间日期字符串转为LocalDate
            System.out.println(autoParseLocalDate("2020-06-09 16:34:14"));
            System.out.println(autoParseLocalDate("2020-06-09 16:34"));
            System.out.println(autoParseLocalDate("2020/06/09 16:34"));
            System.out.println(autoParseLocalDate("2020/06/09"));
            System.out.println(autoParseLocalDate("2020-06-09"));
            System.out.println(autoParseLocalDate("2020-06"));
            System.out.println(autoParseLocalDate("2020/06"));
            System.out.println(autoParseLocalDate("2020"));
    
            // 刚开始写的简单版本,后来发现还可以再扩展就有了上面的autoParseLocalDate
            System.out.println("==================测试出来的彩蛋,自动纠正了,02-31不会抛异常");
            System.out.println(simpleParseStrOfYYYYMMHH("2019/09/30"));
            System.out.println(simpleParseStrOfYYYYMMHH("2019-02-29"));
            System.out.println(simpleParseStrOfYYYYMMHH("2019-02-30"));
            System.out.println(simpleParseStrOfYYYYMMHH("2019-02-31"));
            System.out.println(simpleParseStrOfYYYYMMHH("2019-02-20"));
        }
    }
    
    

    运行上面的main方法测试和输出

    支持格式
    {yyyy-MM=d{4}-d{2}, yyyy/MM=d{4}/d{2}, yyyy/MM/dd=d{4}/d{2}/d{2}, yyyy/MM/dd HH:mm=d{4}/d{2}/d{2} d{2}:d{2}, yyyy-MM-dd HH:mm:ss=d{4}-d{2}-d{2} d{2}:d{2}:d{2}, yyyy=d{4}, yyyy-MM-dd HH:mm=d{4}-d{2}-d{2} d{2}:d{2}, yyyy-MM-dd=d{4}-d{2}-d{2}}
    
    打印结果:
    2020-06-09
    2020-06-09
    2020-06-09
    2020-06-09
    2020-06-09
    2020-06-01
    2020-06-01
    2020-01-01
    2019-09-30
    2019-02-28
    2019-02-28
    2019-02-28
    2019-02-20
    
    
  • 相关阅读:
    CSS3——复杂选择器
    单元测试覆盖率设置
    你必须了解的「架构」小历史
    js正则表达式:学习网址和部分正则验证
    转: js实现全角半角检测的方法
    Linux and the Unix Philosophy(1)
    HTML DOM 对象
    理解css中的 content:" " 是什么意思
    JS
    js
  • 原文地址:https://www.cnblogs.com/zhazhaacmer/p/13515162.html
Copyright © 2011-2022 走看看