Java日期时间API系列42-----一种高效的中文日期格式化和解析方法

xkzhangsanx 2021-09-15 08:24:27
java API 系列 时间 日期


中文日期(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
版权声明
本文为[xkzhangsanx]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/xkzhangsanx/p/15270585.html

  1. Spring中@within与@target的一些区别
  2. 力荐:提高千倍效率的一些 Java 代码小技巧
  3. Redis技术专题系列之帮你从底层彻底吃透RDB技术原理(基础篇)
  4. Juan Benet et vitalik buterin discutent des réflexions sur les médias sociaux décentralisés
  5. Ipfs Weekly Report 152 | pinata launched "submarining"
  6. Performance optimization issue 03 - HTTP request optimization
  7. JavaScript genrator generator
  8. 字节跳动Java面试全套真题解析在互联网火了,面试大厂应该注意哪些问题?
  9. 字节跳动Java社招,2021年阿里 腾讯 快手offer都已拿到!
  10. 用Java实现红黑树
  11. 使用Redis Stream来做消息队列和在Asp.Net Core中的实现
  12. 海量列式非关系数据库HBase 架构,shell与API
  13. Redis Technology Topic Series vous aide à comprendre les principes de la technologie rdb du Bas (Basic)
  14. Conseils: quelques conseils pour améliorer l'efficacité du Code Java
  15. Quelques différences entre @ within et @ Target au printemps
  16. 海量列式非關系數據庫HBase 架構,shell與API
  17. Architecture, Shell et API de base de données non relationnelle à grande échelle
  18. Mise en œuvre de l'arbre Rouge et noir en Java
  19. Byte Hopping Java Service Call, 2021 Alibaba Tencent Express offer a été obtenu!
  20. Byte Jump Java interview Full Set of true Problems Analysis in Internet fire, interview Factory should pay attention to what Problems?
  21. La dernière réponse à l'entrevue de développement Android, l'hiver froid de l'industrie
  22. A young Lexus, the new NX refuses to be mediocre and mature
  23. Interprétation approfondie de l'équipe sin7y: application de plookup dans la conception de zkevm
  24. Java basic knowledge point Combing, redis Common Data Structures and Using scenario Analysis,
  25. Five minutes to understand MySQL index push down
  26. Data structure and algorithm (XI) -- algorithm recursion
  27. Programmation asynchrone Java scirp, développement frontal de base
  28. Java basic knowledge point video, three sides ant Gold Clothing successfully obtained offer,
  29. Oracle Linux bascule le noyau uek vers le noyau rhck pour résoudre les problèmes de compatibilité acfs
  30. After the grand finale of spring in jade mansion, after reading many comments, I began to sympathize with white deer
  31. 字节跳动Java高级工程师,统一命名服务、集群管理、分布式应用?
  32. 字节跳动Java高级工程师,深入分布式缓存从原理到实践技术分享,
  33. 字节跳动第三轮技术面,阿里P8架构师Java大厂面试题总结,
  34. 字节跳动社招Java面试,超通俗解析CountDownLatch用法和源码,
  35. 字节跳动最新开源,最经典的HashMap图文详解,
  36. 字節跳動第三輪技術面,阿裏P8架構師Java大廠面試題總結,
  37. Byte Jumping the Third Third Technical surface, Ali P8 Architect Java Factory Interview Question summary,
  38. L'ingénieur Java senior de Byte Hopping approfondit la mise en cache distribuée, du principe au partage de la technologie pratique.
  39. Byte Jump Java Senior Engineer, Unified Naming service, Cluster Management, Distributed application?
  40. Plusieurs méthodes de transfert de fichiers entre Windows et Linux
  41. 快速从 Windows 切换到 Linux 环境
  42. 五分钟向MySql数据库插入一千万条数据
  43. Java日期时间API系列42-----一种高效的中文日期格式化和解析方法
  44. 用Java实现红黑树
  45. 使用Redis Stream来做消息队列和在Asp.Net Core中的实现
  46. 海量列式非关系数据库HBase 架构,shell与API
  47. Architecture, Shell et API de base de données non relationnelle à grande échelle
  48. Mise en œuvre de l'arbre Rouge et noir en Java
  49. Java Date Time API Series 42 - - a efficient Chinese Date Format and Analysis Method
  50. 5 minutes pour insérer 10 millions de données dans la base de données MySQL
  51. Passage rapide de Windows à l'environnement Linux
  52. Notes on Java backend development of PostgreSQL (I)
  53. 海量列式非關系數據庫HBase 架構,shell與API
  54. Byte Jump the latest open source, the most Classic hashtap Graph details,
  55. L'interview Java de Byte Hopping Society, l'analyse super populaire de l'utilisation et du code source de countdownlatch,
  56. "Anti Mafia storm" Wang Zhifei's love history is really wonderful: he divorced Zhang Xinyi and married a 14-year-old wife
  57. In spring in the jade mansion, Jia Fengyuan was not moved by his brother's death. Why was su Yingxue changed? The reason is realistic
  58. Adam Oracle Oracle fully constructs Adam token incentive for ecological development
  59. 实战SpringCloud通用请求字段拦截处理,超过500人面试阿里,
  60. 宅家36天咸鱼翻身入职腾讯,Zookeeper一致性级别分析,