Files
go-common/docs/datetime.md

597 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 日期转换工具文档
## 概述
日期转换工具提供了丰富的日期时间处理功能,支持时区设定、格式转换、时间计算等常用操作。
**重要说明**:日期时间功能位于 `tools` 包中,推荐通过 `factory` 包使用(黑盒模式),也可以直接使用 `tools` 包。
## 功能特性
- 支持时区设定和转换
- 支持多种时间格式的解析和格式化
- 提供常用时间格式常量
- 支持Unix时间戳转换
- 提供时间计算功能(添加天数、月数、年数等)
- 提供时间范围获取功能(开始/结束时间)
- 支持将任意时区时间转换为UTC时间用于数据库存储
## 使用方法
### 方式1通过 factory 使用(推荐,黑盒模式)
```go
import "git.toowon.com/jimmy/go-common/factory"
// 创建工厂
fac, _ := factory.NewFactoryFromFile("config.json")
// 获取当前时间
now := fac.Now("Asia/Shanghai")
// 格式化时间
str := fac.FormatDateTime(now)
// 解析时间
t, _ := fac.ParseDateTime("2024-01-01 12:00:00", "Asia/Shanghai")
// 时间计算
tomorrow := fac.AddDays(now, 1)
```
### 方式2直接使用 tools 包
```go
import "git.toowon.com/jimmy/go-common/tools"
// 设置默认时区为上海时区
err := tools.SetDefaultTimeZone(tools.AsiaShanghai)
if err != nil {
log.Fatal(err)
}
```
### 2. 获取当前时间
**通过 factory**
```go
// 使用默认时区
now := fac.Now()
// 使用指定时区
now := fac.Now("Asia/Shanghai")
now := fac.Now("America/New_York")
```
**直接使用 tools**
```go
// 使用默认时区
now := tools.Now()
// 使用指定时区
now := tools.Now(tools.AsiaShanghai)
now := tools.Now("America/New_York")
```
### 3. 解析时间字符串
**通过 factory**
```go
// 使用默认时区解析
t, err := fac.ParseDateTime("2024-01-01 12:00:00")
// 使用指定时区解析
t, err := fac.ParseDateTime("2024-01-01 12:00:00", "Asia/Shanghai")
// 解析日期
t, err := fac.ParseDate("2024-01-01")
```
**直接使用 tools**
```go
// 使用默认时区解析
t, err := tools.Parse("2006-01-02 15:04:05", "2024-01-01 12:00:00")
// 使用指定时区解析
t, err := tools.Parse("2006-01-02 15:04:05", "2024-01-01 12:00:00", tools.AsiaShanghai)
// 使用常用格式解析
t, err := tools.ParseDateTime("2024-01-01 12:00:00")
t, err := tools.ParseDate("2024-01-01")
```
### 4. 格式化时间
**通过 factory**
```go
t := time.Now()
// 使用默认时区格式化
str := fac.FormatDateTime(t)
str := fac.FormatDate(t)
str := fac.FormatTime(t)
// 使用指定时区格式化
str := fac.FormatDateTime(t, "Asia/Shanghai")
```
**直接使用 tools**
```go
t := time.Now()
// 使用默认时区格式化
str := tools.Format(t, "2006-01-02 15:04:05")
// 使用指定时区格式化
str := tools.Format(t, "2006-01-02 15:04:05", tools.AsiaShanghai)
// 使用常用格式
str := tools.FormatDateTime(t) // "2006-01-02 15:04:05"
str := tools.FormatDate(t) // "2006-01-02"
str := tools.FormatTime(t) // "15:04:05"
```
### 5. 时区转换
**通过 factory**
```go
t := time.Now()
t2, err := tools.ToTimezone(t, "Asia/Shanghai")
```
**直接使用 tools**
```go
t := time.Now()
t2, err := tools.ToTimezone(t, tools.AsiaShanghai)
```
### 6. Unix时间戳转换
**通过 factory**
```go
t := time.Now()
// 转换为Unix时间戳
unix := fac.ToUnix(t)
// 从Unix时间戳创建时间
t2 := fac.FromUnix(unix)
// 转换为Unix毫秒时间戳
unixMilli := fac.ToUnixMilli(t)
// 从Unix毫秒时间戳创建时间
t3 := fac.FromUnixMilli(unixMilli)
```
**直接使用 tools**
```go
t := time.Now()
// 转换为Unix时间戳
unix := tools.ToUnix(t)
// 从Unix时间戳创建时间
t2 := tools.FromUnix(unix)
// 转换为Unix毫秒时间戳
unixMilli := tools.ToUnixMilli(t)
// 从Unix毫秒时间戳创建时间
t3 := tools.FromUnixMilli(unixMilli)
```
### 7. 时间计算
**通过 factory**
```go
t := time.Now()
// 添加天数
t1 := fac.AddDays(t, 7)
// 添加月数
t2 := fac.AddMonths(t, 1)
// 添加年数
t3 := fac.AddYears(t, 1)
```
**直接使用 tools**
```go
t := time.Now()
// 添加天数
t1 := tools.AddDays(t, 7)
// 添加月数
t2 := tools.AddMonths(t, 1)
// 添加年数
t3 := tools.AddYears(t, 1)
```
### 8. 时间范围获取
**通过 factory**
```go
t := time.Now()
// 获取一天的开始时间00:00:00
start := fac.StartOfDay(t)
// 获取一天的结束时间23:59:59.999999999
end := fac.EndOfDay(t)
// 获取月份的开始时间
monthStart := fac.StartOfMonth(t)
// 获取月份的结束时间
monthEnd := fac.EndOfMonth(t)
// 获取年份的开始时间
yearStart := fac.StartOfYear(t)
// 获取年份的结束时间
yearEnd := fac.EndOfYear(t)
```
**直接使用 tools**
```go
t := time.Now()
// 获取一天的开始时间00:00:00
start := tools.StartOfDay(t)
// 获取一天的结束时间23:59:59.999999999
end := tools.EndOfDay(t)
// 获取月份的开始时间
monthStart := tools.StartOfMonth(t)
// 获取月份的结束时间
monthEnd := tools.EndOfMonth(t)
// 获取年份的开始时间
yearStart := tools.StartOfYear(t)
// 获取年份的结束时间
yearEnd := tools.EndOfYear(t)
```
### 9. 时间差计算
**通过 factory**
```go
t1 := time.Now()
t2 := time.Now().Add(24 * time.Hour)
// 计算天数差
days := fac.DiffDays(t1, t2)
// 计算小时差
hours := fac.DiffHours(t1, t2)
// 计算分钟差
minutes := fac.DiffMinutes(t1, t2)
// 计算秒数差
seconds := fac.DiffSeconds(t1, t2)
```
**直接使用 tools**
```go
t1 := time.Now()
t2 := time.Now().Add(24 * time.Hour)
// 计算天数差
days := tools.DiffDays(t1, t2)
// 计算小时差
hours := tools.DiffHours(t1, t2)
// 计算分钟差
minutes := tools.DiffMinutes(t1, t2)
// 计算秒数差
seconds := tools.DiffSeconds(t1, t2)
```
### 10. 转换为UTC时间用于数据库存储
**直接使用 toolsfactory 暂未提供):**
```go
// 将任意时区的时间转换为UTC
t := time.Now() // 当前时区的时间
utcTime := tools.ToUTC(t)
// 从指定时区转换为UTC
t, _ := tools.ParseDateTime("2024-01-01 12:00:00", tools.AsiaShanghai)
utcTime, err := tools.ToUTCFromTimezone(t, tools.AsiaShanghai)
// 解析时间字符串并直接转换为UTC
utcTime, err := tools.ParseDateTimeToUTC("2024-01-01 12:00:00", tools.AsiaShanghai)
// 解析日期并转换为UTC当天的00:00:00 UTC
utcTime, err := tools.ParseDateToUTC("2024-01-01", tools.AsiaShanghai)
```
## API 参考
### 时区常量
**通过 tools 包使用:**
```go
import "git.toowon.com/jimmy/go-common/tools"
const (
tools.UTC = "UTC"
tools.AsiaShanghai = "Asia/Shanghai"
tools.AmericaNewYork = "America/New_York"
tools.EuropeLondon = "Europe/London"
tools.AsiaTokyo = "Asia/Tokyo"
)
```
### 常用时间格式
```go
CommonLayouts.DateTime = "2006-01-02 15:04"
CommonLayouts.DateTimeSec = "2006-01-02 15:04:05"
CommonLayouts.Date = "2006-01-02"
CommonLayouts.Time = "15:04"
CommonLayouts.TimeSec = "15:04:05"
CommonLayouts.ISO8601 = "2006-01-02T15:04:05Z07:00"
CommonLayouts.RFC3339 = time.RFC3339
CommonLayouts.RFC3339Nano = time.RFC3339Nano
```
### 主要函数
**注意**:以下函数可以通过 `factory``tools` 包调用。推荐使用 `factory` 的黑盒模式。
#### SetDefaultTimeZone(timezone string) error
设置默认时区(仅 tools 包提供)。
**参数:**
- `timezone`: 时区字符串,如 "Asia/Shanghai"
**返回:** 错误信息
**使用方式:**
```go
tools.SetDefaultTimeZone(tools.AsiaShanghai)
```
#### Now(timezone ...string) time.Time
获取当前时间。
**参数:**
- `timezone`: 可选,时区字符串,不指定则使用默认时区
**返回:** 时间对象
**使用方式:**
```go
// 通过 factory
now := fac.Now("Asia/Shanghai")
// 直接使用 tools
now := tools.Now(tools.AsiaShanghai)
```
#### ParseDateTime(value string, timezone ...string) (time.Time, error)
解析日期时间字符串2006-01-02 15:04:05
**参数:**
- `value`: 时间字符串
- `timezone`: 可选,时区字符串
**返回:** 时间对象和错误信息
**使用方式:**
```go
// 通过 factory
t, err := fac.ParseDateTime("2024-01-01 12:00:00", "Asia/Shanghai")
// 直接使用 tools
t, err := tools.ParseDateTime("2024-01-01 12:00:00", tools.AsiaShanghai)
```
#### FormatDateTime(t time.Time, timezone ...string) string
格式化日期时间2006-01-02 15:04:05
**参数:**
- `t`: 时间对象
- `timezone`: 可选,时区字符串
**返回:** 格式化后的时间字符串
**使用方式:**
```go
// 通过 factory
str := fac.FormatDateTime(t, "Asia/Shanghai")
// 直接使用 tools
str := tools.FormatDateTime(t, tools.AsiaShanghai)
```
更多函数请参考 `factory` 包或 `tools` 包的 API 文档。
### UTC转换函数
#### ToUTC(t time.Time) time.Time
将时间转换为UTC时间。
**参数:**
- `t`: 时间对象(可以是任意时区)
**返回:** UTC时间
#### ToUTCFromTimezone(t time.Time, timezone string) (time.Time, error)
从指定时区转换为UTC时间。
**参数:**
- `t`: 时间对象(会被视为指定时区的时间)
- `timezone`: 源时区
**返回:** UTC时间和错误信息
#### ParseToUTC(layout, value string, timezone ...string) (time.Time, error)
解析时间字符串并转换为UTC时间。
**参数:**
- `layout`: 时间格式,如 "2006-01-02 15:04:05"
- `value`: 时间字符串
- `timezone`: 源时区,如果为空则使用默认时区
**返回:** UTC时间和错误信息
#### ParseDateTimeToUTC(value string, timezone ...string) (time.Time, error)
解析日期时间字符串并转换为UTC时间便捷方法
**参数:**
- `value`: 时间字符串(格式: 2006-01-02 15:04:05
- `timezone`: 源时区,如果为空则使用默认时区
**返回:** UTC时间和错误信息
#### ParseDateToUTC(value string, timezone ...string) (time.Time, error)
解析日期字符串并转换为UTC时间便捷方法
**参数:**
- `value`: 日期字符串(格式: 2006-01-02
- `timezone`: 源时区,如果为空则使用默认时区
**返回:** UTC时间当天的00:00:00 UTC时间和错误信息
## 注意事项
1. **时区字符串**必须符合IANA时区数据库格式
2. **默认时区**默认时区为UTC建议在应用启动时设置合适的默认时区
3. **时间格式**时间格式字符串必须使用Go的特定时间2006-01-02 15:04:05
4. **时间范围函数**所有时间范围函数StartOfDay、EndOfDay等都会考虑时区
5. **数据库存储**
- 数据库时间统一使用UTC时间存储
- 使用`ToUTC``ParseToUTC`等方法将时间转换为UTC后存储到数据库
- 从数据库读取UTC时间后使用`ToTimezone`转换为用户时区显示
## 完整示例
### 示例1通过 factory 使用(推荐)
```go
package main
import (
"fmt"
"log"
"git.toowon.com/jimmy/go-common/factory"
)
func main() {
// 创建工厂
fac, err := factory.NewFactoryFromFile("config.json")
if err != nil {
log.Fatal(err)
}
// 获取当前时间
now := fac.Now("Asia/Shanghai")
fmt.Printf("Current time: %s\n", fac.FormatDateTime(now))
// 解析时间
t, err := fac.ParseDateTime("2024-01-01 12:00:00", "Asia/Shanghai")
if err != nil {
log.Fatal(err)
}
// 格式化时间
fmt.Printf("Parsed time: %s\n", fac.FormatDateTime(t))
// 时间计算
tomorrow := fac.AddDays(now, 1)
fmt.Printf("Tomorrow: %s\n", fac.FormatDate(tomorrow))
}
```
### 示例2直接使用 tools 包
```go
package main
import (
"fmt"
"log"
"git.toowon.com/jimmy/go-common/tools"
)
func main() {
// 设置默认时区
err := tools.SetDefaultTimeZone(tools.AsiaShanghai)
if err != nil {
log.Fatal(err)
}
// 获取当前时间
now := tools.Now()
fmt.Printf("Current time: %s\n", tools.FormatDateTime(now))
// 时区转换
t, _ := tools.ParseDateTime("2024-01-01 12:00:00")
t2, _ := tools.ToTimezone(t, tools.AmericaNewYork)
fmt.Printf("Time in New York: %s\n", tools.FormatDateTime(t2))
}
```
### 示例3UTC转换数据库存储场景
```go
package main
import (
"fmt"
"log"
"git.toowon.com/jimmy/go-common/tools"
)
func main() {
// 从请求中获取时间(假设是上海时区)
requestTimeStr := "2024-01-01 12:00:00"
requestTimezone := tools.AsiaShanghai
// 转换为UTC时间用于数据库存储
dbTime, err := tools.ParseDateTimeToUTC(requestTimeStr, requestTimezone)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Request time (Shanghai): %s\n", requestTimeStr)
fmt.Printf("Database time (UTC): %s\n", tools.FormatDateTime(dbTime, tools.UTC))
// 从数据库读取UTC时间转换为用户时区显示
userTimezone := tools.AsiaShanghai
displayTime, err := tools.ToTimezone(dbTime, userTimezone)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Display time (Shanghai): %s\n", tools.FormatDateTime(displayTime, userTimezone))
}
```
完整示例请参考 `factory` 包中的 datetime 相关方法,通过 `factory` 调用 `tools` 包中的 datetime 功能。