中文日期(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日期时间API系列42-----一种高效的中文日期格式化和解析方法的更多相关文章

  1. Java日期时间API系列19-----Jdk8中java.time包中的新的日期时间API类,ZonedDateTime与ZoneId和LocalDateTime的关系,ZonedDateTime格式化和时区转换等。

    通过Java日期时间API系列6-----Jdk8中java.time包中的新的日期时间API类中时间范围示意图:可以很清晰的看出ZonedDateTime相当于LocalDateTime+ZoneI ...

  2. Java日期时间API系列8-----Jdk8中java.time包中的新的日期时间API类的LocalDate源码分析

    目录 0.前言 1.TemporalAccessor源码 2.Temporal源码 3.TemporalAdjuster源码 4.ChronoLocalDate源码 5.LocalDate源码 6.总 ...

  3. Java日期时间API系列11-----Jdk8中java.time包中的新的日期时间API类,使用java8日期时间API重写农历LunarDate

    通过Java日期时间API系列7-----Jdk8中java.time包中的新的日期时间API类的优点,java8具有很多优点,现在网上查到的农历转换工具类都是基于jdk7及以前的类写的,下面使用ja ...

  4. Java日期时间API系列12-----Jdk8中java.time包中的新的日期时间API类,日期格式化,常用日期格式大全

    通过Java日期时间API系列10-----Jdk8中java.time包中的新的日期时间API类的DateTimeFormatter, 可以看出java8的DateTimeFormatter完美解决 ...

  5. Java日期时间API系列13-----Jdk8中java.time包中的新的日期时间API类,时间类转换,Date转LocalDateTime,LocalDateTime转Date等

    从前面的系列博客中可以看出Jdk8中java.time包中的新的日期时间API类设计的很好,但Date由于使用仍非常广泛,这就涉及到Date转LocalDateTime,LocalDateTime转D ...

  6. Java日期时间API系列6-----Jdk8中java.time包中的新的日期时间API类

    因为Jdk7及以前的日期时间类的不方便使用问题和线程安全问题等问题,2005年,Stephen Colebourne创建了Joda-Time库,作为替代的日期和时间API.Stephen向JCP提交了 ...

  7. Java日期时间API系列7-----Jdk8中java.time包中的新的日期时间API类的特点

    1.不变性 新的日期/时间API中,所有的类都是不可变的,这对多线程环境有好处. 比如:LocalDateTime 2.关注点分离 新的API将人可读的日期时间和机器时间(unix timestamp ...

  8. Java日期时间API系列21-----Jdk8中java.time包中的新的日期时间API类,xk-time时间转换,计算,格式化,解析的工具

    通过工作之余,对Java8中java.time包源码的不断学习,使用和总结,开发了xk-time,初步完成,欢迎试用和提出建议! xk-time xk-time is a datetime conve ...

  9. Java日期时间API系列2-----Jdk7及以前的日期时间类在mysql数据库中的应用

    1.java中与数据库相关的时间类 java提供与mysql方便交互的三种数据类型: java.sql.Date java.sql.Time java.sql.Timestamp 它们都是继承java ...

  10. Java日期时间API系列10-----Jdk8中java.time包中的新的日期时间API类的DateTimeFormatter

    1.DateTimeFormatter final修饰,线程安全,用于打印和解析日期-时间对象的格式化程序. 创建DateTimeFormatter: DateTimeFormatter dateTi ...

随机推荐

  1. 通过NPOI操作Excel

    最近在做的一个项目中需要生成Excel,通过学习使用NPOI实现了相关需求,写了一个简便操作的类,记录如下: public class NPOIHelperForExcel { #region exc ...

  2. DIV+CSS常用的网页布局代码

    单行一列以下是引用片段:body { margin: 0px; padding: 0px; text-align: center; }#content { margin-left:auto; marg ...

  3. SQL性能优化注意事项

    1.选用适合的Oracle优化器 Oracle的优化器共有3种: a.RULE(基于规则) b.COST(基于成本) c.CHOOSE(选择性) 设置缺省的优化器,可以通过对init.ora文件中OP ...

  4. openstack私有云布署实践【12.1 网络Neutron-controller节点配置(科兴环境)】

    网络这一块推荐使用的是 Neutron--LinuxBirdge的Ha高可用,此高可用方案对Public作用不是很大,Public只用到DHCP,而Private则会用到L3 Agent,则此方案是有 ...

  5. Python基础之条件语句和循环

    条件语句 Python中的条件语句分为 if ...else . if ...elif...else  以及if ...else 的嵌套使用: username = input('请输入您的用户名:' ...

  6. Codeforces Round #426 Div. 1

    A:考虑每个质因子,显然要求次数之和是3的倍数,且次数之差的两倍不小于较小的次数.对于第一个要求,乘起来看开三次方是否是整数即可.第二个取gcd,两个数分别除掉gcd,之后看两个数的剩余部分是否都能被 ...

  7. 安装Linux系统,学习Linux操作基础

    20189230杨静怡 2018-2019-2 <移动平台开发实践>第1周学习总结 安装Linux系统内容总结 一.学习"基于VirtualBox虚拟机安装Ubuntu图文教程& ...

  8. Python之reduce函数

    描述 reduce() 函数会对参数序列中元素进行累积. 函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给reduce中的函数 function(有两个参数)先对集合中的第 1.2 ...

  9. keras—多层感知器识别手写数字算法程序

    #coding=utf-8 #1.数据预处理 import numpy as np #导入模块,numpy是扩展链接库 import pandas as pd import tensorflow im ...

  10. php—Smarty-缓存1(25)

    一.            缓存原理: IE:将资源文件保存至本地 Smarty:将缓存保存到服务器 编译      <            缓存      <            静 ...