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

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
}