274 lines
7.6 KiB
Go
Executable File
274 lines
7.6 KiB
Go
Executable File
package helper
|
||
|
||
import (
|
||
"fmt"
|
||
"time"
|
||
|
||
"github.com/pkg/errors"
|
||
|
||
"google.golang.org/protobuf/types/known/timestamppb"
|
||
)
|
||
|
||
const (
|
||
DefaultParseFormatLayout = "2006-1-02 15:04:05" // 默认解析时间格式
|
||
DefaultFormatLayout = "2006-01-02 15:04:05" // 默认时间格式
|
||
MicroFormatLayout = "2006-01-02 15:04:05.000000" // 微秒时间格式
|
||
FormatLayout = "20060102150405" // 导出时间格式
|
||
)
|
||
|
||
func AfterMinutesUnix(minutes int64) int64 {
|
||
// 获取当前时间
|
||
currentTime := time.Now()
|
||
// 将当前时间增加5分钟
|
||
currentTime = currentTime.Add(time.Duration(minutes) * time.Minute)
|
||
// 转换为Unix时间戳(秒)
|
||
return currentTime.Unix()
|
||
}
|
||
|
||
func Parse(inputTime string) (time.Time, error) {
|
||
// 设置时区为中国上海
|
||
loc, err := time.LoadLocation("Asia/Shanghai")
|
||
if err != nil {
|
||
return time.Time{}, err
|
||
}
|
||
// 解析时间字符串并指定时区
|
||
parsedTime, err := time.ParseInLocation(DefaultFormatLayout, inputTime, loc)
|
||
if err != nil {
|
||
return time.Time{}, err
|
||
}
|
||
return parsedTime, nil
|
||
}
|
||
|
||
func Parse2(timeStr string) (time.Time, error) {
|
||
//if timeStr == "" {
|
||
// return time.Time{}, fmt.Errorf("时间参数未传递")
|
||
//}
|
||
//timeStr = strings.Replace(timeStr, "+", " ", -1)
|
||
// 解析日期时间字符串
|
||
t, err := time.Parse(DefaultFormatLayout, timeStr)
|
||
if err != nil {
|
||
return time.Time{}, err
|
||
}
|
||
// 获取本地时区的 *time.Location 对象
|
||
local := time.Now().Location()
|
||
// 将时间转换为本地时区的时间
|
||
localTime := t.In(local)
|
||
return localTime, nil
|
||
}
|
||
|
||
func DateStringToTime(localTimeStr string) (time.Time, error) {
|
||
if localTimeStr == "" {
|
||
return time.Time{}, fmt.Errorf("时间参数未传递")
|
||
}
|
||
layouts := []string{
|
||
DefaultParseFormatLayout,
|
||
DefaultFormatLayout,
|
||
"2006-01-02 15:04",
|
||
"2006-1-02 15:04",
|
||
"2006-01-02",
|
||
"2006-1-02",
|
||
time.RFC3339Nano,
|
||
}
|
||
var (
|
||
localTime time.Time
|
||
err error
|
||
)
|
||
loc, _ := time.LoadLocation(GetTimeZone())
|
||
for _, layout := range layouts {
|
||
localTime, err = time.ParseInLocation(layout, localTimeStr, loc)
|
||
if err == nil {
|
||
break
|
||
}
|
||
}
|
||
if err != nil {
|
||
return time.Time{}, fmt.Errorf("时间转换错误:%v", err)
|
||
}
|
||
|
||
return localTime, nil
|
||
}
|
||
|
||
// TimeFormat 时间戳转时间格式
|
||
func TimeFormat(inTime *time.Time, layout ...string) string {
|
||
if inTime == nil {
|
||
return ""
|
||
}
|
||
if len(layout) == 0 {
|
||
layout = []string{DefaultFormatLayout}
|
||
}
|
||
return inTime.Format(layout[0])
|
||
}
|
||
|
||
// TimeStampFormat 时间戳转时间格式
|
||
func TimeStampFormat(timestamp int64, layout ...string) string {
|
||
if timestamp == 0 {
|
||
return ""
|
||
}
|
||
if len(layout) == 0 {
|
||
layout = []string{DefaultFormatLayout}
|
||
}
|
||
return time.Unix(timestamp, 0).Format(layout[0])
|
||
}
|
||
|
||
// Int32TimeStampFormat int32类型时间戳转时间格式
|
||
func Int32TimeStampFormat(timestamp int32, layout ...string) string {
|
||
return TimeStampFormat(int64(timestamp), layout...)
|
||
}
|
||
|
||
// IsoDateStringToTimeStamp iso格式字符串转时间戳
|
||
func IsoDateStringToTimeStamp(isoTimeStr string) (int64, error) {
|
||
isoTime, err := time.ParseInLocation(time.RFC3339Nano, isoTimeStr, time.Local)
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
return isoTime.Unix(), nil
|
||
}
|
||
|
||
// LayOutDateStringToTimeStamp layout格式字符串转时间戳
|
||
func LayOutDateStringToTimeStamp(localTimeStr string) (int64, error) {
|
||
localTime, err := time.ParseInLocation(DefaultFormatLayout, localTimeStr, time.Local)
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
return localTime.Unix(), nil
|
||
}
|
||
|
||
// DateStringToTimeStamp 字符串转时间戳(兼容格式)
|
||
func DateStringToTimeStamp(date string) (int64, error) {
|
||
u, err := IsoDateStringToTimeStamp(date)
|
||
if err != nil {
|
||
u, err = LayOutDateStringToTimeStamp(date)
|
||
}
|
||
return u, err
|
||
}
|
||
|
||
// DateStringToTimeStampInt32 字符串转时间戳(兼容格式)
|
||
func DateStringToTimeStampInt32(date string) (int32, error) {
|
||
u, err := DateStringToTimeStamp(date)
|
||
return int32(u), err
|
||
}
|
||
|
||
// BatchDateStringToTimeStampInt32 批量字符串转时间戳
|
||
func BatchDateStringToTimeStampInt32(dates []string) ([]int32, error) {
|
||
res := make([]int32, 0, len(dates))
|
||
for _, date := range dates {
|
||
u, err := DateStringToTimeStampInt32(date)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
res = append(res, u)
|
||
}
|
||
return res, nil
|
||
}
|
||
|
||
// GoogleTimeToString google proto时间转字符串
|
||
func GoogleTimeToString(date *timestamppb.Timestamp) string {
|
||
loc, _ := time.LoadLocation(GetTimeZone())
|
||
return date.AsTime().In(loc).Format(DefaultFormatLayout)
|
||
}
|
||
|
||
// GoogleTimeToMicroString google proto时间转字符串
|
||
func GoogleTimeToMicroString(date *timestamppb.Timestamp) string {
|
||
loc, _ := time.LoadLocation(GetTimeZone())
|
||
return date.AsTime().In(loc).Format(MicroFormatLayout)
|
||
}
|
||
|
||
func DateStringToTimeStampV2(localTimeStr string) (int64, error) {
|
||
if localTimeStr == "" {
|
||
return 0, nil
|
||
}
|
||
|
||
layouts := []string{
|
||
DefaultParseFormatLayout,
|
||
DefaultFormatLayout,
|
||
"2006-01-02 15:04",
|
||
"2006-1-02 15:04",
|
||
"2006-01-02",
|
||
"2006-1-02",
|
||
time.RFC3339Nano,
|
||
}
|
||
|
||
var (
|
||
localTime time.Time
|
||
err error
|
||
)
|
||
|
||
loc, _ := time.LoadLocation(GetTimeZone())
|
||
for _, layout := range layouts {
|
||
localTime, err = time.ParseInLocation(layout, localTimeStr, loc)
|
||
if err == nil {
|
||
break
|
||
}
|
||
}
|
||
|
||
if err != nil {
|
||
return 0, errors.Errorf("解析时间错误: %s", err.Error())
|
||
}
|
||
|
||
return localTime.Unix(), nil
|
||
}
|
||
|
||
// IsTimeStrBefore 时间比较 格式:2006-01-02 15:04:05
|
||
func IsTimeStrBefore(beforeTime, afterTime string) bool {
|
||
time1, _ := time.Parse(DefaultFormatLayout, beforeTime)
|
||
time2, _ := time.Parse(DefaultFormatLayout, afterTime)
|
||
if time1.Before(time2) {
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
// IsTimeBefore 时间比较 格式:2006-01-02 15:04:05,beforeTime[2024-01-10 00:00:00]小于afterTime[2024-01-02 00:00:00]返回true
|
||
func IsTimeBefore(beforeTime, afterTime time.Time) bool {
|
||
if beforeTime.Before(afterTime) {
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
// IsTimeBeforeOrEqual 时间比较 格式:2006-01-02 15:04:05,beforeTime[2024-01-10 00:00:00]小于等于afterTime[2024-01-02 00:00:00]返回true
|
||
func IsTimeBeforeOrEqual(beforeTime, afterTime time.Time) bool {
|
||
b := beforeTime.Before(afterTime) || beforeTime.Equal(afterTime)
|
||
if b {
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
// IsInSameNaturalMonth 判断两个时间是否在同一个自然月
|
||
func IsInSameNaturalMonth(startTime, endTime time.Time) bool {
|
||
// 将 startTime 和 endTime 的日期统一到该月的12号
|
||
startYear, startMonth, _ := startTime.Date()
|
||
endYear, endMonth, _ := endTime.Date()
|
||
|
||
// 如果月份不同,调整 endTime 到 startTime 的同一天(同月)
|
||
if startYear == endYear && startMonth == endMonth {
|
||
return true
|
||
}
|
||
|
||
// 处理跨月情况, 检查如果 startTime 和 endTime 跨越到下一个月的同一天
|
||
// 比如:如果 startTime 是 12 号,则 endTime 应该是下个月的12号
|
||
expectedEndTime := time.Date(endYear, endMonth, startTime.Day(), startTime.Hour(), startTime.Minute(), startTime.Second(), 0, time.Local)
|
||
|
||
// 如果 endTime 的日期和调整后的 expectedEndTime 相同,则认为它们属于同一个自然月
|
||
return expectedEndTime.Year() == endTime.Year() &&
|
||
expectedEndTime.Month() == endTime.Month() &&
|
||
expectedEndTime.Day() == endTime.Day() &&
|
||
expectedEndTime.Hour() == endTime.Hour() &&
|
||
expectedEndTime.Minute() == endTime.Minute() &&
|
||
expectedEndTime.Second() == endTime.Second()
|
||
}
|
||
|
||
func DaysBetween(start, end time.Time) (int, error) {
|
||
// 2. 统一到同一天的 0 点(避免时分秒干扰)
|
||
startDay := start.Truncate(24 * time.Hour)
|
||
endDay := end.Truncate(24 * time.Hour)
|
||
|
||
// 3. 计算天数(含结束日)
|
||
days := int(endDay.Sub(startDay).Hours() / 24)
|
||
if end.After(endDay) { // 结束时间非 0 点,加 1 天
|
||
days++
|
||
}
|
||
|
||
return days, nil
|
||
}
|