# dateparse_demo
**Repository Path**: leaveWhite9088/dateparse_demo
## Basic Information
- **Project Name**: dateparse_demo
- **Description**: 项目dateparse的演示demo
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2025-05-13
- **Last Updated**: 2025-05-13
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
dateparse
## 介绍
dateparse 是一个基于 cangjie 标准库实现的高性能、功能丰富的日期时间解析库。它能够自动识别并解析多种格式的日期字符串,支持全球各种常见日期格式,包括各种区域标准、时区处理以及多语言日期表示。该库适合需要处理各种不同格式日期输入的应用程序。
### 项目特性
- **多格式支持**:自动识别并解析几十种常见日期格式,无需指定格式模板。
- **时区处理**:内置全面的时区支持,可在不同时区之间准确转换。
- **灵活配置**:提供多种解析选项,可定制解析行为。
- **高性能实现**:经过优化的解析算法,处理速度快,资源占用少。
- 本项目参考了项目 [dateparse](https://github.com/araddon/dateparse),结合仓颉的时间解析特性设计
### 项目计划
- 2025/3/12 function freeze
- 2025/3/15 添加更多本地化日期格式支持
- 2025/3/21 优化性能并减少内存占用
- 2025/3/25 增加日期格式化功能模块
- 2025/3/28 新增支持的日期格式
## 项目架构
架构图文说明,包括模块说明、架构层次等详细说明。
### 源码目录
```shell
.
├── README.md #整体介绍
├── doc #文档目录(计划中)
│ ├── design.md #设计文档
│ └── feature_api.md #特性接口文档
├── src #源码目录
│ ├── date_parse.cj #主类,提供对外API接口
│ ├── parser.cj #核心解析器实现
│ ├── parser_options.cj #解析选项配置
│ ├── parser_option.cj #解析选项接口
│ ├── constant.cj #常量定义
│ ├── util.cj #工具函数
│ ├── exception_ambiguous.cj #日期格式歧义异常
│ ├── exception_unknown.cj #未知日期格式异常
│ └── test #测试代码
│ ├── date_parse_test.cj #测试用例
└── cjpm.toml #项目配置文件
```
### 接口说明
主要类和函数接口说明如下,详见 API文档(计划中)
#### DateParse类
```cangjie
/** 解析任意格式的日期字符串
* 自动检测字符串格式并转换为 DateTime 对象,使用 UTC 时区
*
* @param dateStr 要解析的日期字符串
* @param loc 可选的时区信息,如果不提供则使用本地时区
* @param opts 可选的解析选项
* @return 解析后的 DateTime 对象
*/
public func parseAny(dateStr: String, loc: ?TimeZone, opts: ?Array): DateTime
```
```cangjie
/** 在指定时区解析日期字符串
* 自动检测字符串格式并转换为指定时区的 DateTime 对象
*
* @param dateStr 要解析的日期字符串
* @param loc 目标时区
* @param opts 可选的解析选项
* @return 解析后的 DateTime 对象
*/
public func parseIn(dateStr: String, loc: TimeZone, opts: ?Array): DateTime
```
```cangjie
/** 在本地时区解析日期字符串
* 自动检测字符串格式并转换为本地时区的 DateTime 对象
*
* @param dateStr 要解析的日期字符串
* @param opts 可选的解析选项
* @return 解析后的 DateTime 对象
*/
public func parseLocal(dateStr: String, opts: ?Array): DateTime
```
```cangjie
/** 解析日期字符串,错误时抛出异常
* 如果解析失败则会抛出异常而不是返回错误
*
* @param dateStr 要解析的日期字符串
* @param loc 可选的时区信息,如果不提供则使用 UTC 时区
* @param opts 可选的解析选项
* @return 解析后的 DateTime 对象
* @throws Exception 如果无法解析日期字符串
*/
public func mustParse(dateStr: String, loc: ?TimeZone, opts: ?Array): DateTime
```
```cangjie
/** 获取日期字符串的格式模板
* 解析日期并返回其格式字符串,而不是 DateTime 对象
*
* @param dateStr 要解析的日期字符串
* @param loc 可选的时区信息,如果不提供则使用本地时区
* @param opts 可选的解析选项
* @return 日期字符串的格式
*/
public func parseFormat(dateStr: String, loc: ?TimeZone, opts: ?Array): String
```
```cangjie
/** 获取处理后的日期字符串
* 解析日期并返回其格式字符串,而不是 DateTime 对象
*
* @param dateStr 要解析的日期字符串
* @param loc 可选的时区信息,如果不提供则使用本地时区
* @param opts 可选的解析选项
* @return 日期字符串的格式
*/
public func parseDateStr(dateStr: String, loc: ?TimeZone, opts: ?Array): String
```
```cangjie
/**
* 获取处理后的日期字符串和格式模板
* 解析日期并返回字符串数组,而不是 DateTime 对象
*
* @param dateStr 要解析的日期字符串
* @param loc 可选的时区信息,如果不提供则使用本地时区
* @param opts 可选的解析选项
* @return 日期字符串的格式
*/
public func parseStrAndFormat(dateStr: String, loc: ?TimeZone, opts: ?Array): Array
```
```cangjie
/** 严格解析日期字符串
* 如果日期格式存在歧义(如月/日顺序不确定)则抛出异常
*
* @param dateStr 要解析的日期字符串
* @param loc 可选的时区信息,如果不提供则使用本地时区
* @param opts 可选的解析选项
* @return 解析后的 DateTime 对象
* @throws ExceptionAmbiguous 如果日期格式存在歧义
*/
public func parseStrict(dateStr: String, loc: ?TimeZone, opts: ?Array): DateTime
```
#### ParserOptions类
```cangjie
/** 创建设置是否优先将第一个数字解析为月份的选项
* @param preferMonthFirst 如果为 true,则优先将第一个数字解析为月份;否则优先解析为日期
* @return 配置月份优先的解析选项
*/
public static func preferMonthFirst(preferMonthFirst: Bool): ParserOption
```
```cangjie
/** 创建设置是否在月份解析出错时尝试交换日期和月份的选项
* @param retryAmbiguousDateWithSwap 如果为 true,则在月份超出范围时尝试交换日期和月份
* @return 配置交换重试的解析选项
*/
public static func retryAmbiguousDateWithSwap(retryAmbiguousDateWithSwap: Bool): ParserOption
```
## 使用说明
### 编译构建
描述具体的编译过程:
```shell
cjpm update
cjpm build
```
### 功能示例
#### 解析多种格式日期功能示例
功能示例描述: 这个示例展示了如何解析各种不同格式的日期字符串,而无需指定具体格式。
示例代码如下:
```cangjie
import dateparse.*
import std.collection.HashMap
import std.time.DateTime
main() {
// 实例时间格式
let mainInputs = HashMap([
// 标准日期时间格式
("May 8, 2009 5:57:51 PM","2009-05-08T17:57:51+08:00"),
// 简单月日年格式
("oct 7, 1970","1970-10-07T00:00:00+08:00"),
("oct 7, '70","1970-10-07T00:00:00+08:00"),
("oct. 7, 1970","1970-10-07T00:00:00+08:00"),
("oct. 7, 70","1970-10-07T00:00:00+08:00"),
// Go的标准时间格式
("Mon Jan 2 15:04:05 2006","2006-01-02T15:04:05+08:00"),
("Mon Jan 2 15:04:05 MST 2006","2006-01-02T15:04:05-07:00"),
("Mon Jan 02 15:04:05 -0700 2006","2006-01-02T15:04:05-07:00"),
("Monday, 02-Jan-06 15:04:05 MST","2006-01-02T15:04:05-07:00"),
("Mon, 02 Jan 2006 15:04:05 MST","2006-01-02T15:04:05-07:00"),
// 带时区的日期时间格式
("Tue, 11 Jul 2017 16:28:13 +0200 CEST","2017-07-11T16:28:13+04:00"),
("Mon, 02 Jan 2006 15:04:05 -0700","2006-01-02T15:04:05-07:00"),
("Mon Aug 10 15:44:11 UTC+0100 2015","2015-08-10T15:44:11+01:00"),
("Thu, 4 Jan 2018 17:53:36 +0000","2018-01-04T17:53:36Z"),
("Fri Jul 03 2015 18:04:07 GMT+0100 (GMT Daylight Time)","2015-07-03T18:04:07+01:00"),
("Sun, 3 Jan 2021 00:12:23 +0800 (GMT+08:00)","2021-01-03T00:12:23+08:00"),
// 美式日期时间格式
("September 17, 2012 10:09am","2012-09-17T10:09:00+08:00"),
("September 17, 2012 at 10:09am PST-08:00","2012-09-17T10:09:00-16:00"),
("September 17, 2012, 10:10:09","2012-09-17T10:10:09+08:00"),
("October 7, 1970","1970-10-07T00:00:00+08:00"),
("October 7th, 1970","1970-10-07T00:00:00+08:00"),
// 欧式日期时间格式
("12 Feb 2006, 19:17","2006-02-12T19:17:00+08:00"),
("12 Feb 2006 19:17","2006-02-12T19:17:00+08:00"),
("14 May 2019 19:11:40.164","2019-05-14T19:11:40.164+08:00"),
("7 oct 70","1970-10-07T00:00:00+08:00"),
("7 oct 1970","1970-10-07T00:00:00+08:00"),
("03 February 2013","2013-02-03T00:00:00+08:00"),
("1 July 2013","2013-07-01T00:00:00+08:00"),
("2013-Feb-03","2013-02-03T00:00:00+08:00"),
// Apache日志格式
("06/Jan/2008:15:04:05 -0700","2008-01-06T15:04:05-07:00"),
("06/Jan/2008 15:04:05 -0700","2008-01-06T15:04:05-07:00"),
// mm/dd/yy格式
("3/31/2014","2014-03-31T00:00:00+08:00"),
("03/31/2014","2014-03-31T00:00:00+08:00"),
("08/21/71","1971-08-21T00:00:00+08:00"),
("8/1/71","1971-08-01T00:00:00+08:00"),
("4/8/2014 22:05","2014-04-08T22:05:00+08:00"),
("04/08/2014 22:05","2014-04-08T22:05:00+08:00"),
("4/8/14 22:05","2014-04-08T22:05:00+08:00"),
("04/2/2014 03:00:51","2014-04-02T03:00:51+08:00"),
// 12小时制时间格式
("8/8/1965 12:00:00 AM","1965-08-08T00:00:00+08:00"),
("8/8/1965 01:00:01 PM","1965-08-08T13:00:01+08:00"),
("8/8/1965 01:00 PM","1965-08-08T13:00:00+08:00"),
("8/8/1965 1:00 PM","1965-08-08T13:00:00+08:00"),
("8/8/1965 12:00 AM","1965-08-08T00:00:00+08:00"),
// 带毫秒的时间格式
("4/02/2014 03:00:51","2014-04-02T03:00:51+08:00"),
("03/19/2012 10:11:59","2012-03-19T10:11:59+08:00"),
("03/19/2012 10:11:59.3186369","2012-03-19T10:11:59.3186369+08:00"),
// yyyy/mm/dd格式
("2014/3/31","2014-03-31T00:00:00+08:00"),
("2014/03/31","2014-03-31T00:00:00+08:00"),
("2014/4/8 22:05","2014-04-08T22:05:00+08:00"),
("2014/04/08 22:05","2014-04-08T22:05:00+08:00"),
("2014/04/2 03:00:51","2014-04-02T03:00:51+08:00"),
("2014/4/02 03:00:51","2014-04-02T03:00:51+08:00"),
("2012/03/19 10:11:59","2012-03-19T10:11:59+08:00"),
("2012/03/19 10:11:59.3186369","2012-03-19T10:11:59.3186369+08:00"),
// yyyy:mm:dd格式
("2014:3:31","2014-03-31T00:00:00+08:00"),
("2014:03:31","2014-03-31T00:00:00+08:00"),
("2014:4:8 22:05","2014-04-08T22:05:00+08:00"),
("2014:04:08 22:05","2014-04-08T22:05:00+08:00"),
("2014:04:2 03:00:51","2014-04-02T03:00:51+08:00"),
("2014:4:02 03:00:51","2014-04-02T03:00:51+08:00"),
("2012:03:19 10:11:59","2012-03-19T10:11:59+08:00"),
("2012:03:19 10:11:59.3186369","2012-03-19T10:11:59.3186369+08:00"),
// ISO 8601格式
("2006-01-02T15:04:05+0800","2006-01-02T15:04:05+08:00"),
("2009-08-12T22:15:09-07:00","2009-08-12T22:15:09-07:00"),
("2009-08-12T22:15:09","2009-08-12T22:15:09+08:00"),
("2009-08-12T22:15:09.988","2009-08-12T22:15:09.988+08:00"),
("2009-08-12T22:15:09","2009-08-12T22:15:09+08:00"),
("2017-07-19T03:21:51.897+0100","2017-07-19T03:21:51.897+01:00"),
("2019-05-29T08:41-04","2019-05-29T08:41:00-04:00"),
// 标准日期时间带毫秒
("2014-04-26 17:24:37.3186369","2014-04-26T17:24:37.3186369+08:00"),
("2012-08-03 18:31:59.257000000","2012-08-03T18:31:59.257+08:00"),
("2014-04-26 17:24:37.123","2014-04-26T17:24:37.123+08:00"),
// 简单日期时间
("2013-04-01 22:43","2013-04-01T22:43:00+08:00"),
("2013-04-01 22:43:22","2013-04-01T22:43:22+08:00"),
// UTC/GMT时间
("2014-12-16 06:20:00 UTC","2014-12-16T06:20:00Z"),
("2014-12-16 06:20:00 GMT","2014-12-16T06:20:00Z"),
// 12小时制和时区组合
("2014-04-26 05:24:37 PM","2014-04-26T17:24:37+08:00"),
("2014-04-26 13:13:43 +0800","2014-04-26T13:13:43+08:00"),
("2014-04-26 13:13:43 +0800 +08","2014-04-26T13:13:43+08:00"),
("2014-04-26 13:13:44 +09:00","2014-04-26T13:13:44+09:00"),
// UTC时间戳格式
("2012-08-03 18:31:59.257000000 +0000 UTC","2012-08-03T18:31:59.257Z"),
("2015-09-30 18:48:56.35272715 +0000 UTC","2015-09-30T18:48:56.35272715Z"),
("2015-02-18 00:12:00 +0000 GMT","2015-02-18T00:12:00Z"),
("2015-02-18 00:12:00 +0000 UTC","2015-02-18T00:12:00Z"),
("2017-07-19 03:21:51+00:00","2017-07-19T03:21:51Z"),
// 仅日期
("2014-04-26","2014-04-26T00:00:00+08:00"),
// 带逗号的毫秒格式
("2014-05-11 08:20:13,787","2014-05-11T08:20:13.787+08:00"),
// 带时区的简单日期
("2020-07-20+08:00","2020-07-20T00:00:00+08:00"),
// 点分隔的日期格式
("3.31.2014","2014-03-31T00:00:00+08:00"),
("03.31.2014","2014-03-31T00:00:00+08:00"),
("08.21.71","1971-08-21T00:00:00+08:00"),
("2014.03.30","2014-03-30T00:00:00+08:00"),
// 紧凑格式
("20140601","2014-06-01T00:00:00+08:00"),
("20140722105203","2014-07-22T10:52:03+08:00"),
("171113 14:14:20","2017-11-13T14:14:20+08:00"),
// Unix时间戳格式
("1332151919","2012-03-19T10:11:59+08:00"),
("1384216367189","2013-11-12T00:32:47.189+08:00"),
("1384216367111222","2013-11-12T00:32:47.111222+08:00"),
("1384216367111222333","2013-11-12T00:32:47.111222333+08:00")
])
// 创建解析器实例
let parser = DateParse.default
// 循环输出解析后的时间
println("┌────────────────────────────────────────────┬────────────────────────────────────────────┐")
println("│ 输入日期字符串 │ 实际解析结果 │")
println("├────────────────────────────────────────────┼────────────────────────────────────────────┤")
for (item in mainInputs){
var ts: DateTime = parser.parseAny(item[0], None, None)
var actual = ts.toString()
// 使用朴素方法而不是padEnd
var inputStr = "│ " + item[0]
while (inputStr.size < 47) {
inputStr += " "
}
var outputStr = "│ " + actual
while (outputStr.size < 46) {
outputStr += " "
}
println(inputStr + outputStr + " │")
}
println("└────────────────────────────────────────────┴────────────────────────────────────────────┘")
}
```
执行结果如下:
```shell
┌────────────────────────────────────────────┬────────────────────────────────────────────┐
│ 输入日期字符串 │ 实际解析结果 │
├────────────────────────────────────────────┼────────────────────────────────────────────┤
│ May 8, 2009 5:57:51 PM │ 2009-05-08T17:57:51+08:00 │
│ oct 7, 1970 │ 1970-10-07T00:00:00+08:00 │
│ oct 7, '70 │ 1970-10-07T00:00:00+08:00 │
│ oct. 7, 1970 │ 1970-10-07T00:00:00+08:00 │
│ oct. 7, 70 │ 1970-10-07T00:00:00+08:00 │
│ Mon Jan 2 15:04:05 2006 │ 2006-01-02T15:04:05+08:00 │
│ Mon Jan 2 15:04:05 MST 2006 │ 2006-01-02T15:04:05-07:00 │
│ Mon Jan 02 15:04:05 -0700 2006 │ 2006-01-02T15:04:05-07:00 │
│ Monday, 02-Jan-06 15:04:05 MST │ 2006-01-02T15:04:05-07:00 │
│ Mon, 02 Jan 2006 15:04:05 MST │ 2006-01-02T15:04:05-07:00 │
│ Tue, 11 Jul 2017 16:28:13 +0200 CEST │ 2017-07-11T16:28:13+04:00 │
│ Mon, 02 Jan 2006 15:04:05 -0700 │ 2006-01-02T15:04:05-07:00 │
│ Mon Aug 10 15:44:11 UTC+0100 2015 │ 2015-08-10T15:44:11+01:00 │
│ Thu, 4 Jan 2018 17:53:36 +0000 │ 2018-01-04T17:53:36Z │
│ Sun, 3 Jan 2021 00:12:23 +0800 (GMT+08:00) │ 2021-01-03T00:12:23+08:00 │
│ September 17, 2012 10:09am │ 2012-09-17T10:09:00+08:00 │
│ September 17, 2012 at 10:09am PST-08:00 │ 2012-09-17T10:09:00-16:00 │
│ September 17, 2012, 10:10:09 │ 2012-09-17T10:10:09+08:00 │
│ October 7, 1970 │ 1970-10-07T00:00:00+08:00 │
│ October 7th, 1970 │ 1970-10-07T00:00:00+08:00 │
│ 12 Feb 2006, 19:17 │ 2006-02-12T19:17:00+08:00 │
│ 12 Feb 2006 19:17 │ 2006-02-12T19:17:00+08:00 │
│ 14 May 2019 19:11:40.164 │ 2019-05-14T19:11:40.164+08:00 │
│ 7 oct 70 │ 1970-10-07T00:00:00+08:00 │
│ 7 oct 1970 │ 1970-10-07T00:00:00+08:00 │
│ 03 February 2013 │ 2013-02-03T00:00:00+08:00 │
│ 1 July 2013 │ 2013-07-01T00:00:00+08:00 │
│ 2013-Feb-03 │ 2013-02-03T00:00:00+08:00 │
│ 06/Jan/2008:15:04:05 -0700 │ 2008-01-06T15:04:05-07:00 │
│ 06/Jan/2008 15:04:05 -0700 │ 2008-01-06T15:04:05-07:00 │
│ 3/31/2014 │ 2014-03-31T00:00:00+08:00 │
│ 03/31/2014 │ 2014-03-31T00:00:00+08:00 │
│ 08/21/71 │ 1971-08-21T00:00:00+08:00 │
│ 8/1/71 │ 1971-08-01T00:00:00+08:00 │
│ 4/8/2014 22:05 │ 2014-04-08T22:05:00+08:00 │
│ 04/08/2014 22:05 │ 2014-04-08T22:05:00+08:00 │
│ 4/8/14 22:05 │ 2014-04-08T22:05:00+08:00 │
│ 04/2/2014 03:00:51 │ 2014-04-02T03:00:51+08:00 │
│ 8/8/1965 12:00:00 AM │ 1965-08-08T00:00:00+08:00 │
│ 8/8/1965 01:00:01 PM │ 1965-08-08T13:00:01+08:00 │
│ 8/8/1965 01:00 PM │ 1965-08-08T13:00:00+08:00 │
│ 8/8/1965 1:00 PM │ 1965-08-08T13:00:00+08:00 │
│ 8/8/1965 12:00 AM │ 1965-08-08T00:00:00+08:00 │
│ 4/02/2014 03:00:51 │ 2014-04-02T03:00:51+08:00 │
│ 03/19/2012 10:11:59 │ 2012-03-19T10:11:59+08:00 │
│ 03/19/2012 10:11:59.3186369 │ 2012-03-19T10:11:59.3186369+08:00 │
│ 2014/3/31 │ 2014-03-31T00:00:00+08:00 │
│ 2014/03/31 │ 2014-03-31T00:00:00+08:00 │
│ 2014/4/8 22:05 │ 2014-04-08T22:05:00+08:00 │
│ 2014/04/08 22:05 │ 2014-04-08T22:05:00+08:00 │
│ 2014/04/2 03:00:51 │ 2014-04-02T03:00:51+08:00 │
│ 2014/4/02 03:00:51 │ 2014-04-02T03:00:51+08:00 │
│ 2012/03/19 10:11:59 │ 2012-03-19T10:11:59+08:00 │
│ 2012/03/19 10:11:59.3186369 │ 2012-03-19T10:11:59.3186369+08:00 │
│ 2014:3:31 │ 2014-03-31T00:00:00+08:00 │
│ 2014:03:31 │ 2014-03-31T00:00:00+08:00 │
│ 2014:4:8 22:05 │ 2014-04-08T22:05:00+08:00 │
│ 2014:04:08 22:05 │ 2014-04-08T22:05:00+08:00 │
│ 2014:04:2 03:00:51 │ 2014-04-02T03:00:51+08:00 │
│ 2014:4:02 03:00:51 │ 2014-04-02T03:00:51+08:00 │
│ 2012:03:19 10:11:59 │ 2012-03-19T10:11:59+08:00 │
│ 2012:03:19 10:11:59.3186369 │ 2012-03-19T10:11:59.3186369+08:00 │
│ 2006-01-02T15:04:05+0800 │ 2006-01-02T15:04:05+08:00 │
│ 2009-08-12T22:15:09-07:00 │ 2009-08-12T22:15:09-07:00 │
│ 2009-08-12T22:15:09 │ 2009-08-12T22:15:09+08:00 │
│ 2009-08-12T22:15:09.988 │ 2009-08-12T22:15:09.988+08:00 │
│ 2017-07-19T03:21:51.897+0100 │ 2017-07-19T03:21:51.897+01:00 │
│ 2019-05-29T08:41-04 │ 2019-05-29T08:41:00-04:00 │
│ 2014-04-26 17:24:37.3186369 │ 2014-04-26T17:24:37.3186369+08:00 │
│ 2012-08-03 18:31:59.257000000 │ 2012-08-03T18:31:59.257+08:00 │
│ 2014-04-26 17:24:37.123 │ 2014-04-26T17:24:37.123+08:00 │
│ 2013-04-01 22:43 │ 2013-04-01T22:43:00+08:00 │
│ 2013-04-01 22:43:22 │ 2013-04-01T22:43:22+08:00 │
│ 2014-12-16 06:20:00 UTC │ 2014-12-16T06:20:00Z │
│ 2014-12-16 06:20:00 GMT │ 2014-12-16T06:20:00Z │
│ 2014-04-26 05:24:37 PM │ 2014-04-26T17:24:37+08:00 │
│ 2014-04-26 13:13:43 +0800 │ 2014-04-26T13:13:43+08:00 │
│ 2014-04-26 13:13:43 +0800 +08 │ 2014-04-26T13:13:43+08:00 │
│ 2014-04-26 13:13:44 +09:00 │ 2014-04-26T13:13:44+09:00 │
│ 2012-08-03 18:31:59.257000000 +0000 UTC │ 2012-08-03T18:31:59.257Z │
│ 2015-09-30 18:48:56.35272715 +0000 UTC │ 2015-09-30T18:48:56.35272715Z │
│ 2015-02-18 00:12:00 +0000 GMT │ 2015-02-18T00:12:00Z │
│ 2015-02-18 00:12:00 +0000 UTC │ 2015-02-18T00:12:00Z │
│ 2017-07-19 03:21:51+00:00 │ 2017-07-19T03:21:51Z │
│ 2014-04-26 │ 2014-04-26T00:00:00+08:00 │
│ 2014-05-11 08:20:13,787 │ 2014-05-11T08:20:13.787+08:00 │
│ 2020-07-20+08:00 │ 2020-07-20T00:00:00+08:00 │
│ 3.31.2014 │ 2014-03-31T00:00:00+08:00 │
│ 03.31.2014 │ 2014-03-31T00:00:00+08:00 │
│ 08.21.71 │ 1971-08-21T00:00:00+08:00 │
│ 2014.03.30 │ 2014-03-30T00:00:00+08:00 │
│ 20140601 │ 2014-06-01T00:00:00+08:00 │
│ 20140722105203 │ 2014-07-22T10:52:03+08:00 │
│ 171113 14:14:20 │ 2017-11-13T14:14:20+08:00 │
│ 1332151919 │ 2012-03-19T10:11:59+08:00 │
│ 1384216367189 │ 2013-11-12T00:32:47.189+08:00 │
│ 1384216367111222 │ 2013-11-12T00:32:47.111222+08:00 │
│ 1384216367111222333 │ 2013-11-12T00:32:47.111222333+08:00 │
└────────────────────────────────────────────┴────────────────────────────────────────────┘
```
#### 时区处理功能示例
功能示例描述: 此示例展示了如何在不同时区解析日期字符串,并进行时区转换。
示例代码如下:
```cangjie
import dateparse.*
import std.time.TimeZone
main() {
// 创建解析器实例
let parser = DateParse.default
// 在不同时区解析相同的日期字符串
let dateUTC = parser.parseIn("2023-01-15 12:00:00", TimeZone.UTC, None)
let dateLocal = parser.parseLocal("2023-01-15 12:00:00", None)
// 输出结果
println("UTC时间: " + dateUTC.toString("yyyy-MM-dd HH:mm:ss z"))
println("本地时间: " + dateLocal.toString("yyyy-MM-dd HH:mm:ss z"))
}
```
执行结果如下:
```shell
UTC时间: 2023-01-15 12:00:00 GMT
本地时间: 2023-01-15 12:00:00 UTC+08:00
```
#### 格式识别功能示例
功能示例描述: 这个示例展示了如何获取日期字符串的格式模板。特别注意:由于本库对原始字符串有所处理,所以最后使用的格式不一定能够直接解析原字符串
示例代码如下:
```cangjie
import dateparse.*
import std.time.*
main() {
// 创建解析器实例
let parser = DateParse.default
// 识别各种日期格式
let format1 = parser.parseFormat("2023-01-15", None, None)
let format2 = parser.parseFormat("Jan 15, 2023", None, None)
// 处理后的日期字符串
let dateStr1 = parser.parseDateStr("2023-01-15", None, None)
let dateStr2 = parser.parseDateStr("Jan 15, 2023", None, None)
// 获取处理后的日期字符串和格式模板
let temp = parser.parseStrAndFormat("2023-01-15", None, None)
let dateStr3 = temp[0]
let format3 = temp[1]
let temp2 = parser.parseStrAndFormat("Jan 15, 2023", None, None)
let dateStr4 = temp2[0]
let format4 = temp2[1]
// 输出识别的格式
println("处理后的日期字符串1: " + dateStr1)
println("识别的格式1: " + format1)
println("--------------------------------")
println("处理后的日期字符串2: " + dateStr2)
println("识别的格式2: " + format2)
println("--------------------------------")
println("处理后的日期字符串3: " + dateStr3)
println("识别的格式3: " + format3)
println("--------------------------------")
println("处理后的日期字符串4: " + dateStr4)
println("识别的格式4: " + format4)
}
```
执行结果如下:
```shell
处理后的日期字符串1: 2023-01-15
识别的格式1: y-MM-dd
--------------------------------
处理后的日期字符串2: Jan 15, 2023
识别的格式2: MMM dd, y
--------------------------------
处理后的日期字符串3: 01/15/2023
识别的格式3: MM/dd/y
--------------------------------
处理后的日期字符串4: 2023/01/15 15:04:05
识别的格式4: y/MM/dd H:m:s
```
#### 严格解析功能示例
功能示例描述: 此示例展示了如何使用严格解析模式,避免月/日顺序歧义。
示例代码如下:
```cangjie
import dateparse.*
main() {
// 创建解析器实例
let parser = DateParse.default
// 配置解析选项
let opts = [
ParserOptions.preferMonthFirst(false), // 优先将第一个数字解析为日期,而非月份
ParserOptions.retryAmbiguousDateWithSwap(false) // 不自动尝试交换月/日
]
try {
// 尝试严格解析可能有歧义的日期
let date = parser.parseStrict("04/05/2023", None, opts)
println("解析结果: " + date.toString("yyyy-MM-dd"))
} catch (e: ExceptionAmbiguous) {
println("日期格式存在歧义: " + e.message)
} catch (e: Exception) {
println("解析错误: " + e.message)
}
// 解析无歧义的日期
try {
let date = parser.parseStrict("2023-04-05", None, None)
println("解析结果: " + date.toString("yyyy-MM-dd"))
} catch (e: Exception) {
println("解析错误: " + e.message)
}
}
```
执行结果如下:
```shell
日期格式存在歧义: This date has ambiguous mm/dd vs dd/mm type format
解析结果: 2023-04-05
```
#### 配置解析选项功能示例
功能示例描述: 该示例展示了如何配置解析选项来自定义解析器的行为。
示例代码如下:
```cangjie
import dateparse.*
main() {
// 创建解析器实例
let parser = DateParse.default
var ts = parser.parseAny("04/02/2014 04:08:09 +0000 UTC", None, None)
println("默认格式解析: ${ts.toString()}")
let preferMonthFirstTrue = ParserOptions.preferMonthFirst(true)
ts = parser.parseAny("04/02/2014 04:08:09 +0000 UTC", None, [preferMonthFirstTrue])
println("美式格式解析: ${ts.toString()}")
let preferMonthFirstFalse = ParserOptions.preferMonthFirst(false)
ts = parser.parseAny("04/02/2014 04:08:09 +0000 UTC", None, [preferMonthFirstFalse])
println("欧式格式解析: ${ts.toString()}")
let retryAmbiguousDateWithSwapTrue = ParserOptions.retryAmbiguousDateWithSwap(true)
ts = DateParse.default.parseAny("13/02/2014 04:08:09 +0000 UTC", None, [retryAmbiguousDateWithSwapTrue])
println("自动重试解析结果: ${ts.toString()}")
}
```
执行结果如下:
```shell
默认格式解析: 2014-04-02T04:08:09Z
美式格式解析: 2014-04-02T04:08:09Z
欧式格式解析: 2014-02-04T04:08:09Z
自动重试解析结果: 2014-02-13T04:08:09Z
```
## 约束与限制
- 部分罕见的日期格式可能无法自动识别,需要手动指定格式
- 在处理有歧义的日期格式(如MM/DD vs DD/MM)时,默认采用美式格式(MM/DD)
- 对于以下格式,由于仓颉语言的时间解释特性和该库的实现方式,暂不支持
| 不支持的格式 | 示例 |
| ------------------------------------------ | ----------------------------------------------- |
| `ANSIC_GLIBC` | `Mon 02 Jan 2006 03:04:05 PM UTC` |
| `中文日期格式` | `2014年04月18日` |
| `扩展的 ISO 8601 格式(带时区和额外信息)` | `2015-02-08 03:02:00 +0200 CEST m=+0.000000001` |
| `RFC 2822 格式` | `Tue, 11 Jul 2017 04:08:03 +0200 (CEST)` |
## 开源协议
本项目基于 MIT License
## 参与贡献
本项目基于测试用例开发,所以可能会有一些格式会有疏漏,在使用过程中,如果您发现不支持的格式,欢迎给我们提交PR,欢迎给我们提交Issue,欢迎参与任何形式的贡献。
本项目committer:[@leaveWhite088](https://gitcode.com/leaveWhite9088)
This project is supervised by [@zhangyin_gitcode](https://gitcode.com/zhangyin_gitcode) (HUAWEI Developer Advocate).
