You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
377 lines
7.9 KiB
377 lines
7.9 KiB
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
|
|
}
|