zoukankan      html  css  js  c++  java
  • Java日期时间API系列42-----一种高效的中文日期格式化和解析方法

      中文日期(2021年09月11日 和 二〇二一年九月十一日 )在生活中经常用到,2021年09月11日很好处理直接使用模板:yyyy年MM月dd日;二〇二一年九月十一日比较不好处理,需要每个数字进行转换判断,下面使用数组和HashMap来提高效率和简化代码。

    1.数字转换枚举类

    比较关键,将0到31和中文关联起来,同时生成数组和HashMap。

    package com.xkzhangsan.time.enums;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.function.Supplier;
    
    import com.xkzhangsan.time.utils.CollectionUtil;
    import com.xkzhangsan.time.utils.CommonCache;
    
    /**
     * 中文日期数字枚举
     *
     * @author xkzhangsan
     */
    public enum ChineseDateDigitEnum {
        
        ZERO("〇"),
        ONE("一"),
        TWO("二"),
        THREE("三"),
        FOUR("四"),
        FIVE("五"),
        SIX("六"),
        SEVEN("七"),
        EIGHT("八"),
        NINE("九"),
        TEN("十"),
        ELEVEN("十一"),
        TWELVE("十二"),
        THIRTEEN("十三"),
        FOURTEEN("十四"),
        FIFTEEN("十五"),
        SIXTEEN("十六"),
        SEVENTEEN("十七"),
        EIGHTEEN("十八"),
        NINETEEN("十九"),
        TWENTY("二十"),
        TWENTYONE("二十一"),
        TWENTYTWO("二十二"),
        TWENTYTHREE("二十三"),
        TWENTYFOUR("二十四"),
        TWENTYFIVE("二十五"),
        TWENTYSIX("二十六"),
        TWENTYSEVEN("二十七"),
        TWENTYEIGHT("二十八"),
        TWENTYNINE("二十九"),
        THIRTY("三十"),
        THIRTYONE("三十一");
        
        public static final ChineseDateDigitEnum[] ENUMS = ChineseDateDigitEnum.values();
        
        public static final String CHINESE_DATE_DIGIT_MAP = "CHINESE_DATE_DIGIT_MAP";
        
        private String chineseDigit;
    
        private ChineseDateDigitEnum(String chineseDigit) {
            this.chineseDigit = chineseDigit;
        }
    
        public String getChineseDigit() {
            return chineseDigit;
        }
        
        @SuppressWarnings("unchecked")
        public static Integer getIndexUseCache(String chineseDigit){
            Map<String, Integer> chineseDateDigitMap = new HashMap<>(32);
            
            //查询缓存
            chineseDateDigitMap = (Map<String, Integer>)CommonCache.get(CHINESE_DATE_DIGIT_MAP);
            
            //缓存存在,返回缓存
            if(CollectionUtil.isNotEmpty(chineseDateDigitMap)){
                return chineseDateDigitMap.get(chineseDigit);
            }
            
            //缓存不存在,先设置缓存然后返回
            Supplier<Object> supplier = new Supplier<Object>() {
                @Override
                public Object get() {
                    Map<String, Integer> dateDigitMap = new HashMap<>();
                    
                    for(ChineseDateDigitEnum chineseDateDigitEnum : ENUMS){
                        dateDigitMap.put(chineseDateDigitEnum.getChineseDigit(), chineseDateDigitEnum.ordinal());
                    }
                    return dateDigitMap;
                }
            };
            return ((Map<String, Integer>)CommonCache.get(CHINESE_DATE_DIGIT_MAP, supplier)).get(chineseDigit);
        }
        
    
    }

    2.格式化

    ChineseDateDigitEnum.ENUMS[localDateTime.getDayOfMonth()] ,通过枚举数组下标取值,效率非常高。
        /**
         * 中文日期格式化,isUpperCase false:2021年09月11日 true: 二〇二一年九月十一日
         * @param date Date
         * @param isUpperCase 是否大写,false:2021年09月11日 true: 二〇二一年九月十一日
         * @return String
         */
        public static String formatToChineseDateStr(Date date, boolean isUpperCase){
            return formatToChineseDateStr(DateTimeConverterUtil.toLocalDateTime(date), isUpperCase);
        }
        
        /**
         * 中文日期格式化,isUpperCase false:2021年09月11日 true: 二〇二一年九月十一日
         * @param localDateTime LocalDateTime
         * @param isUpperCase 是否大写,false:2021年09月11日 true: 二〇二一年九月十一日
         * @return String
         */
        public static String formatToChineseDateStr(LocalDateTime localDateTime, boolean isUpperCase){
            Objects.requireNonNull(localDateTime, "localDateTime");
            if(isUpperCase){
                StringBuilder buf = new StringBuilder();
                //
                String year = String.valueOf(localDateTime.getYear());
                int yearLength = year.length();
                for(int i=0; i<yearLength; i++){
                    buf.append(ChineseDateDigitEnum.ENUMS[year.charAt(i)-48].getChineseDigit());
                }
                buf.append("年");
                //
                buf.append(ChineseDateDigitEnum.ENUMS[localDateTime.getMonthValue()].getChineseDigit());
                buf.append("月");
                //
                buf.append(ChineseDateDigitEnum.ENUMS[localDateTime.getDayOfMonth()].getChineseDigit());
                buf.append("日");
                return buf.toString();
            }else{
                return format(localDateTime, YYYY_MM_DD_CN_FMT);
            }
        }

    3.解析

    ChineseDateDigitEnum.getIndexUseCache(dayStrArr[0]) ,通过将数字转换枚举类转换为HashMap,并且使用缓存将map缓存起来,效率非常高。
        /**
         * 中文日期解析  2021年09月11日 或 二〇二一年九月十一日,返回Date
         * @param text 2021年09月11日 或 二〇二一年九月十一日
         * @return Date
         */
        public static Date parseChineseDateStrToDate(String text){
            return DateTimeConverterUtil.toDate(parseChineseDateStrToLocalDateTime(text));
        }
        
        /**
         * 中文日期解析  2021年09月11日 或 二〇二一年九月十一日,返回LocalDateTime
         * @param text 2021年09月11日 或 二〇二一年九月十一日
         * @return LocalDateTime
         */
        public static LocalDateTime parseChineseDateStrToLocalDateTime(String text){
            if(StringUtil.isEmpty(text)){
                throw new NullPointerException("text");
            }
            text = text.trim();
            Pattern pattern = RegexEnum.NormYearFour.getPattern();
            Matcher match = pattern.matcher(text);
            if (match.find()){
                return parseToLocalDateTime(text, YYYY_MM_DD_CN_FMT);
            } else {
                StringBuilder buf = new StringBuilder();
                //
                String[] yearStrArr = text.split("年");
                String yearStr = yearStrArr[0];
                int yearStrLength = yearStr.length();
                for(int i=0; i<yearStrLength; i++){
                    buf.append(ChineseDateDigitEnum.getIndexUseCache(String.valueOf(yearStr.charAt(i))));
                }
                int year = Integer.parseInt(buf.toString());
                //
                String[] monthStrArr = yearStrArr[1].split("月");
                int month = ChineseDateDigitEnum.getIndexUseCache(monthStrArr[0]);
                //
                String[] dayStrArr = monthStrArr[1].split("日");
                int day = ChineseDateDigitEnum.getIndexUseCache(dayStrArr[0]);
                return LocalDateTime.of(year, month, day, 0, 0);
            }
        }

    4.测试

        /**
         * 中文日期格式化测试
         */
        @Test
        public void formatToChineseDateStrTest(){
            Date date = DateTimeCalculatorUtil.getDate(2021, 9, 11);
            Assert.assertEquals("2021年09月11日",DateTimeFormatterUtil.formatToChineseDateStr(date, false));
            Assert.assertEquals("二〇二一年九月十一日",DateTimeFormatterUtil.formatToChineseDateStr(date, true));
            
            LocalDateTime localDateTime = LocalDateTime.of(2021, 9, 11, 0, 0);
            Assert.assertEquals("2021年09月11日",DateTimeFormatterUtil.formatToChineseDateStr(localDateTime, false));
            Assert.assertEquals("二〇二一年九月十一日",DateTimeFormatterUtil.formatToChineseDateStr(localDateTime, true));
        }
        
        /**
         * 中文日期解析测试
         */
        @Test
        public void parseChineseDateStrToDateTest(){
            Date date = DateTimeCalculatorUtil.getDate(2021, 8, 31);
            Assert.assertEquals(date, DateTimeFormatterUtil.parseChineseDateStrToDate("2021年08月31日"));
            Assert.assertEquals(date, DateTimeFormatterUtil.parseChineseDateStrToDate("二〇二一年八月三十一日"));
            
            LocalDateTime localDateTime = LocalDateTime.of(2021, 8, 31, 0, 0);
            Assert.assertEquals(localDateTime, DateTimeFormatterUtil.parseChineseDateStrToLocalDateTime("2021年08月31日"));
            Assert.assertEquals(localDateTime, DateTimeFormatterUtil.parseChineseDateStrToLocalDateTime("二〇二一年八月三十一日"));
        }
    源代码地址:https://github.com/xkzhangsan/xk-time
    寻找撬动地球的支点(解决问题的方案),杠杆(Java等编程语言)已经有了。xkzhangsan
  • 相关阅读:
    CSS——制作天天生鲜主页
    HTML——制作一个图片列表
    HTML——制作一个简易菜单栏
    CSS——三种页面引入方法
    【20170903】模拟赛
    【LA 3942】 Remember the word
    【BZOJ 1036】 树的统计count
    UVA 12299 RMQ with shifts
    【20170706】次短路
    【20170706】保卫萝卜
  • 原文地址:https://www.cnblogs.com/xkzhangsanx/p/15270585.html
Copyright © 2011-2022 走看看