这种比较简单,比如,今天,明天,下周,下月,明年,昨天,上周,上月,去年等。原理:匹配到明天就根据今天的时间天数加1。
  

  1. /**
  2. * 常用时间枚举
  3. *
  4. * @author xkzhangsan
  5. */
  6. public enum CommonTimeEnum {
  7. TODAY("today", "今天"),
  8. TOMORROW("tomorrow", "明天"),
  9. NEXTWEEK("nextWeek", "下周"),
  10. NEXTMONTH("nextMonth", "下月"),
  11. NEXTYEAR("nextYear", "明年"),
  12. YESTERDAY("yesterday", "昨天"),
  13. LASTWEEK("lastWeek", "上周"),
  14. LASTMONTH("lastMonth", "上月"),
  15. LASTYEAR("lastYear", "去年"),
  16. ;
  17. private String code;
  18. private String name;
  19. public String getCode() {
  20. return code;
  21. }
  22. public String getName() {
  23. return name;
  24. }
  25. CommonTimeEnum(String code, String name) {
  26. this.code = code;
  27. this.name = name;
  28. }
  29. public static Map<String, String> convertToMap(){
  30. Map<String, String> commonTimeMap = new HashMap<String, String>();
  31. for (CommonTimeEnum commonTimeEnum : CommonTimeEnum.values()) {
  32. commonTimeMap.put(commonTimeEnum.getCode(), commonTimeEnum.getCode());
  33. commonTimeMap.put(commonTimeEnum.getName(), commonTimeEnum.getCode());
  34. }
  35. return commonTimeMap;
  36. }
  37. public static CommonTimeEnum getCommonTimeEnumByCode(String code){
  38. for (CommonTimeEnum commonTimeEnum : CommonTimeEnum.values()) {
  39. if(commonTimeEnum.getCode().equals(code)){
  40. return commonTimeEnum;
  41. }
  42. }
  43. return null;
  44. }
  45. }
  46. /**
  47. * 解析自然语言时间,今天,明天,下周,下月,明年,昨天,上周,上月,去年等。
  48. * @param text 自然语言时间,待解析字符串
  49. * @param naturalLanguageMap 自定义自然语言时间map,其中key自定义,value需为 com.xkzhangsan.time.enums.CommonTimeEnum中的code;
  50. * 可以为空,默认使用com.xkzhangsan.time.enums.CommonTimeEnum解析。
  51. * @return Date
  52. */
  53. public static Date parseNaturalLanguageToDate(String text, Map<String, String> naturalLanguageMap){
  54. if(StringUtil.isEmpty(text)){
  55. return null;
  56. }
  57. text = text.trim();
  58. boolean isCommonTimeMap = false;
  59. if(CollectionUtil.isEmpty(naturalLanguageMap)){
  60. naturalLanguageMap = CommonTimeEnum.convertToMap();
  61. isCommonTimeMap = true;
  62. }
  63. if(! naturalLanguageMap.containsKey(text) || StringUtil.isEmpty(naturalLanguageMap.get(text))){
  64. return null;
  65. }
  66. String targetMethod = null;
  67. if(isCommonTimeMap){
  68. targetMethod = naturalLanguageMap.get(text);
  69. }else{
  70. String code = naturalLanguageMap.get(text);
  71. Map<String, String> commonTimeMap = CommonTimeEnum.convertToMap();
  72. if(commonTimeMap.containsKey(code)){
  73. targetMethod = commonTimeMap.get(code);
  74. }
  75. }
  76. if(targetMethod == null){
  77. return null;
  78. }
  79. //执行结果
  80. CommonTimeEnum targetCommonTime = CommonTimeEnum.getCommonTimeEnumByCode(targetMethod);
  81. if(targetCommonTime == null){
  82. return null;
  83. }
  84. switch (targetCommonTime){
  85. case TODAY :
  86. return DateTimeCalculatorUtil.today();
  87. case TOMORROW:
  88. return DateTimeCalculatorUtil.tomorrow();
  89. case NEXTWEEK:
  90. return DateTimeCalculatorUtil.nextWeek();
  91. case NEXTMONTH:
  92. return DateTimeCalculatorUtil.nextMonth();
  93. case NEXTYEAR:
  94. return DateTimeCalculatorUtil.nextYear();
  95. case YESTERDAY:
  96. return DateTimeCalculatorUtil.yesterday();
  97. case LASTWEEK:
  98. return DateTimeCalculatorUtil.lastWeek();
  99. case LASTMONTH:
  100. return DateTimeCalculatorUtil.lastMonth();
  101. case LASTYEAR:
  102. return DateTimeCalculatorUtil.lastYear();
  103. default:
  104. return null;
  105. }
  106. }
  107. /**
  108. * 明天
  109. * @return Date
  110. */
  111. public static Date tomorrow(){
  112. return plusDays(today(), 1);
  113. }
  114. /**
  115. * 今天
  116. * @return Date
  117. */
  118. public static Date today(){
  119. return new Date();
  120. }

 

 

这个是真实语境下的时间识别,比如 Hi,all.下周一下午三点开会,如果今天是2021-06-10 那么 返回结果为:2021-06-14 15:00:00 。

 

原理和第一种类似,也是识别时间词语,根据基准时间推断结果,但更强大一些。

基本分为三步:

(1)加载正则文件

(2)解析中文语句中的所有时间词语

(3)根据基准时间,循环解析(2)中的时间词语

详细步骤如图: 

                                                              

github: https://github.com/shinyke/Time-NLP

author:shinyke

由复旦NLP中的时间分析功能修改而来,做了很多细节和功能的优化。

  1. 泛指时间的支持,如:早上、晚上、中午、傍晚等。
  2. 时间未来倾向。 如:在周五输入“周一早上开会”,则识别到下周一早上的时间;在下午17点输入:“9点送牛奶给隔壁的汉子”则识别到第二天上午9点。
  3. 多个时间的识别,及多个时间之间上下文关系处理。如:”下月1号下午3点至5点到图书馆还书”,识别到开始时间为下月1号下午三点。同时,结束时间也继承上文时间,识别到下月1号下午5点。
  4. 可自定义基准时间:指定基准时间为“2016-05-20-09-00-00-00”,则一切分析以此时间为基准。
  5. 修复了各种各样的BUG。

简而言之,这是一个输入一句话,能识别出话里的时间的工具。

 

https://github.com/xkzhangsan/xk-time TimeNLPUtil

在Time-NLP基础上做了很多优化:

(1)封装属性,重命名使符合驼峰命名标准。
(2)将加载正则资源文件改为单例加载。
(3)将类按照功能重新划分为单独的多个类。
(4)使用Java8日期API重写。
(5)增加注释说明,优化代码。
(6)修复原项目中的issue:标准时间yyyy-MM-dd、yyyy-MM-dd HH:mm:ss和yyyy-MM-dd HH:mm解析问题。
(7)修复原项目中的issue:1小时后,1个半小时后,1小时50分钟等解析问题;并且支持到秒,比如50秒后,10分钟30秒后等。
(8)修复原项目中的issue:修复当前时间是上午10点,那么下午三点 会识别为明天下午三点问题。
(9)修复原项目中的issue:修复小数解析异常问题。
(10)性能优化,将使用到的正则预编译后放到缓存中,下次直接使用,提高性能。

 

第一种只能识别单词;

第二种也只能识别正则文件中的词语,比第一种识别能力更强,但如果有新的或不常用的时间词语无法处理,比如星期一的同义词礼拜一等,如果要不断支持新的词语,需要不断的修改,不如机器学习好;

对于常用的时间词语识别,第二种已经达到很高的识别率。

 

 

第一种实现,因为有网友需要识别中文时间词语,我写了第一种的实现;

第二种实现,另一个网友有需要识别语句中的中文时间词语,他向往推荐了Time-NLP这个项目,说这个项目很好,不维护了,有一些小问题,希望我能参考实现,我研究了原项目代码,在我的项目中重写,优化,并修复了一些问题。

感谢shinyke,这个项目很好,学习到很多正则解析的知识。

 

 源码地址: https://github.com/xkzhangsan/xk-time

版权声明:本文为xkzhangsanx原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/xkzhangsanx/p/14873321.html