package util import ( "fmt" "math" "strings" "time" gptypes "github.com/golang/protobuf/ptypes" gptime "github.com/golang/protobuf/ptypes/timestamp" "github.com/shopspring/decimal" "github.com/sirupsen/logrus" ) const ( DEFAULT_LAYOUT = "2006-01-02 15:04:05" DATE_LAYOUT = "2006-01-02" TIME_LAYOUT = "15:04:05" DEFAULT_TIME = "1900-01-01 00:00:00" //0000-00-00 00:00:00 0001-01-01 00:00:00 STR_LAYOUT = "2006-01-02T15:04:05Z07:00" ) func Now() time.Time { return time.Now().UTC() } func NowPtr() *time.Time { now := Now() return &now } func Format(layout string, t time.Time) string { return t.Format(layout) } func FormatByDefLay(t time.Time) string { return Format(DEFAULT_LAYOUT, t) } func Parse(layout string, s string) *time.Time { t, err := time.Parse(layout, s) if err != nil { panic(err) } return &t } func ParseByDefLay(s string) *time.Time { return Parse(DEFAULT_LAYOUT, s) } func IsDefaultTime(t time.Time) bool { defTime := time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC) return defTime.Equal(t.UTC()) } //检查日期 t 是否为日期时间零值:0001-01-01 00:00:00 +0000 UTC func IsTimeZero(t time.Time) bool { timeZero := time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC) return timeZero.Equal(t.UTC()) } func Time2Ts(t time.Time) *gptime.Timestamp { if IsTimeZero(t) { return nil } ts, err := gptypes.TimestampProto(t) if err != nil { return nil } return ts } func Uint8ToTs(b *[]uint8) *gptime.Timestamp { if b == nil || len(*b) == 0 { return nil } s := string(*b) return Str2TsByDefLay(s) } func Ts2Time(ts *gptime.Timestamp) *time.Time { if ts == nil { return nil } t, err := gptypes.Timestamp(ts) if err != nil { logrus.Error(err) return nil } if IsTimeZero(t) { return nil } return &t } func Str2TsByDefLay(s string) *gptime.Timestamp { if s == "" { return nil } return Str2Ts("2006-01-02 15:04:05", s) } func Str2Ts(layout, s string) *gptime.Timestamp { if s == "" { return nil } if layout == "" { return Str2TsByDefLay(s) } t := Parse(layout, s) return Time2Ts(*t) } func Ts2StrByDefLay(ts *gptime.Timestamp) string { return Ts2Str("2006-01-02 15:04:05", ts) } func Ts2Str(layout string, ts *gptime.Timestamp) string { t := Ts2Time(ts) if t == nil { return "" } return Format(layout, *t) } //计算截止到当前时间,指定出生日期对应的年龄描述,如:不足1小时、1小时、1天、1个月、1 岁、1岁1个月、1岁1个月5天 // func CovAgeCnAtNow(birth time.Time) (day int, ageCn string) { now := time.Now() if !Before(birth, now) { return 0, "" } since := now.Sub(birth) hoursSince := int(RoundDecimal(since.Hours(), 0)) daySince := hoursSince / 24 if hoursSince < 1.0 { return daySince, "不足一小时" } if hoursSince < 24 { return daySince, fmt.Sprintf("%d 小时", hoursSince) } yearSince := now.Year() - birth.Year() monthSince := now.Month() - birth.Month() //dayDiff := now.Day() - birth.Day() if yearSince == 0 { //同一年 if monthSince == 0 { //同一月 if daySince == 0 { //同一天 return 0, "不足一天" } else if daySince > 0 { return daySince, fmt.Sprintf("%d 天", daySince) } else { return 0, "" } } else if monthSince > 0 { if daySince == 0 { //同一天 return hoursSince / 24, fmt.Sprintf("%d 个月", monthSince) } else if daySince > 0 { return daySince, fmt.Sprintf("%d 天", daySince) } else { return 0, "" } } else { } } else if yearSince > 0 { } else { } return 0, "" } //根据结束日期和开始日期,计算年龄,返回包含年龄单位(岁、月、天)的字符串 //开始日期一般为用户生日,结束日期一般为当前时间 func CovAgeChinese(start time.Time, end time.Time) (float32, string) { if IsDefaultTime(start) { return 0, "" } //start = start.UTC() //end = end.UTC() diff := end.Unix() - start.Unix() if diff < 0 { return 0, "" } visitAge := decimal.NewFromFloat(float64(diff)).Div(decimal.NewFromFloat(float64(3600 * 365 * 24))) f64, _ := visitAge.Float64() y := decimal.NewFromFloat(float64(diff)).Div(decimal.NewFromFloat(float64(3600 * 365 * 24))) yf, _ := y.Float64() duration := end.Sub(start) //三个月以下 if yf*12 < 3 { days := duration.Hours() / 24 return float32(f64), fmt.Sprintf("%.0f天", math.Ceil(days)) } //三个月以上三岁以下 if yf*12 > 3 && yf < 3 { year := duration.Hours() / (24 * 365) years := int(year) months := (year - float64(years)) * 12 months = math.Floor(months + 0.5) imonths := int(RoundDecimal(months, 0)) sAge := fmt.Sprintf("%d岁", int(years)) if imonths == 12 { sAge = fmt.Sprintf("%d岁", int(years+1)) } else if imonths > 12 { sAge = fmt.Sprintf("%d岁%d个月", int(years+1), imonths-12) } else if imonths < 12 && imonths > 0 { if years == 0 { sAge = fmt.Sprintf("%d个月", imonths) } else { sAge = fmt.Sprintf("%d岁%d个月", int(years), imonths) } } return float32(f64), sAge } //三岁以上 if yf > 3 { years := duration.Hours() / (24 * 365) years = RoundDecimal(years, 0) return float32(f64), fmt.Sprintf("%d岁", int(years)) } return 0, "" /*age, ageUnit := CovAgeInt(start, end) if age <= 0 { return "未知" } return GetChineseAge(age, ageUnit)*/ } func GetChineseAge(age int, ageUnit string) string { if age <= 0 { return "" } switch ageUnit { case "Y": return fmt.Sprintf("%d %s", age, "岁") case "M": return fmt.Sprintf("%d %s", age, "个月") case "D": return fmt.Sprintf("%d %s", age, "天") case "H": return "1 天" //fmt.Sprintf( "%d %s", num, "小时") case "m": return "1 天" //fmt.Sprintf( "%d %s", num, "分钟") case "S": return "1 天" //fmt.Sprintf( "%d %s", num, "秒") case "N": return "1 天" //fmt.Sprintf( "%d %s", num, "纳秒") default: return "1 天" } } func CovAgeInt(start time.Time, end time.Time) (int, string) { start = start.UTC() end = end.UTC() if !Before(start, end) { return 0, "" } if end.Year() > start.Year() { //不同年 return end.Year() - start.Year(), "Y" } else { //同一年 if end.Month() > start.Month() { //不同月 return int(end.Month()) - int(start.Month()), "M" } else { //同一月 if end.Day() > start.Day() { //不同天 return end.Day() - start.Day(), "D" } else { //同一天 if end.Hour() > start.Hour() { //不同小时 return end.Hour() - start.Hour(), "H" } else { //同一小时 if end.Minute() > start.Minute() { //不同分钟 return end.Minute() - start.Minute(), "m" } else { //同一分钟 if end.Second() > start.Second() { //不同秒 return end.Second() - start.Second(), "S" } } } } } } return end.Nanosecond() - start.Nanosecond(), "N" } //判断是否start为早于end的时间,只判断年月日 func Before(start time.Time, end time.Time) bool { if start.Year() < end.Year() { return true } if start.Year() > end.Year() { return false } if start.Year() == end.Year() { //同一年 if start.Month() < end.Month() { return true } if start.Month() > end.Month() { return false } if start.Month() == end.Month() { //同一月 if start.Day() < end.Day() { return true } if start.Day() > end.Day() { return false } if start.Day() == end.Day() { return true //同一天,暂时返回true } } } return end.Nanosecond() >= start.Nanosecond() } func StartTime(t time.Time) time.Time { return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()) } func EndTime(t time.Time) time.Time { return time.Date(t.Year(), t.Month(), t.Day(), 23, 59, 59, 0, t.Location()) } func Strisemptyorzerotime(str string) (res *time.Time) { if strings.TrimSpace(str) == "" { return nil } t1, e1 := time.Parse(DEFAULT_LAYOUT, str) if e1 != nil { t2, e2 := time.Parse(STR_LAYOUT, str) if e2 != nil { // t3, e3 := time.Parse(DATE_LAYOUT, str) if e3 != nil { // return nil } return &t3 } return &t2 } return &t1 }