diff --git a/datetime.go b/datetime.go index ffb37a4..b8b7df9 100644 --- a/datetime.go +++ b/datetime.go @@ -6,6 +6,7 @@ import ( ) type FormatTemplate string +type AddUnits string const ( FormatYear FormatTemplate = "YYYY" @@ -13,6 +14,7 @@ const ( FormatMonth FormatTemplate = "MM" FormatShortMonth FormatTemplate = "M" FormatDay FormatTemplate = "dd" + FormatUpperDay FormatTemplate = "DD" FormatShortDay FormatTemplate = "d" FormatHour FormatTemplate = "HH" FormatShortHour FormatTemplate = "H" @@ -25,6 +27,14 @@ const ( FormatShortWeek FormatTemplate = "WW" ) +const ( + AddYearUnit AddUnits = "year" + AddShortUnit AddUnits = "Y" + AddDaysUnit AddUnits = "day" + AddDaysShortUnit AddUnits = "D" + AddDaysShortLowerUnit AddUnits = "d" +) + func DateTimeFormat(date time.Time, format string) string { formatted := format formatMap := map[FormatTemplate]int{ @@ -34,6 +44,7 @@ func DateTimeFormat(date time.Time, format string) string { FormatShortMonth: int(date.Month()), FormatDay: date.Day(), FormatShortDay: date.Day(), + FormatUpperDay: date.Day(), FormatHour: date.Hour(), FormatShortHour: date.Hour() % 12, FormatSecond: date.Second(), @@ -45,7 +56,7 @@ func DateTimeFormat(date time.Time, format string) string { FormatShortWeek: int(date.Weekday()), } - for _, key := range []FormatTemplate{FormatYear, FormatMonth, FormatShortYear, FormatShortMonth, FormatDay, FormatShortDay, FormatHour, FormatShortHour, FormatSecond, FormatShortSecond, FormatMinute, FormatShortMinute, FormatMillisecond, FormatWeek, FormatShortWeek} { + for _, key := range []FormatTemplate{FormatYear, FormatMonth, FormatShortYear, FormatShortMonth, FormatDay, FormatUpperDay, FormatShortDay, FormatHour, FormatShortHour, FormatSecond, FormatShortSecond, FormatMinute, FormatShortMinute, FormatMillisecond, FormatWeek, FormatShortWeek} { formatted = strings.Replace( formatted, string(key), @@ -63,3 +74,283 @@ func DateTimeFormat(date time.Time, format string) string { return formatted } + +type FormatCallback func(int) string + +type DateTime struct { + time time.Time + Year int + Month int + Day int + Week int + Hour int + Minute int + Second int + Milliseconds int + Nanosecond int + DateFormat string + TimeFormat string + monthFormat FormatCallback + weekFormat FormatCallback +} + +func NewDateTime() DateTime { + d := DateTime{ + time: time.Now(), + DateFormat: "YYYY-MM-DD", + TimeFormat: "HH:mm:ss.ms", + } + d.Year = d.time.Year() + d.Month = int(d.time.Month()) + d.Day = d.time.Day() + d.Hour = d.time.Hour() + d.Minute = d.time.Minute() + d.Second = d.time.Second() + d.Nanosecond = d.time.Nanosecond() + return d +} + +func (dt DateTime) SetYear(year int, month int, day int, hour int, minute int, second int, nanosecond int) DateTime { + d := DateTime{ + time: time.Date(year, time.Month(month), day, hour, minute, second, nanosecond, time.UTC), + DateFormat: dt.DateFormat, + TimeFormat: dt.TimeFormat, + monthFormat: dt.monthFormat, + weekFormat: dt.weekFormat, + } + d.Year = d.time.Year() + d.Month = int(d.time.Month()) + d.Day = d.time.Day() + d.Hour = d.time.Hour() + d.Minute = d.time.Minute() + d.Second = d.time.Second() + d.Nanosecond = d.time.Nanosecond() + return d +} + +func (dt DateTime) SetMonth(month int, day int, hour int, minute int, second int, nanosecond int) DateTime { + return dt.SetYear(dt.Year, month, day, hour, minute, second, nanosecond) +} + +func (dt DateTime) SetDate(day int, hour int, minute int, second int, nanosecond int) DateTime { + return dt.SetYear(dt.Year, dt.Month, day, hour, minute, second, nanosecond) +} + +func (dt DateTime) SetHour(hour int, minute int, second int, nanoseconds int) DateTime { + return dt.SetYear(dt.Year, dt.Month, dt.Day, hour, minute, second, nanoseconds) +} + +func (dt DateTime) SetMinute(minute int, second int, nanoseconds int) DateTime { + return dt.SetHour(dt.Hour, minute, second, nanoseconds) +} + +func (dt DateTime) SetSecond(second int, nanoseconds int) DateTime { + return dt.SetMinute(dt.Minute, second, nanoseconds) +} + +func (dt DateTime) SetMilliseconds(milliseconds int, nanosecond int) DateTime { + return dt.SetHour(dt.Hour, dt.Minute, 0, milliseconds*int(time.Millisecond)+nanosecond) +} + +func (dt DateTime) SetNanosecond(nanoseconds int) DateTime { + return dt.SetSecond(dt.Second, nanoseconds) +} + +func (dt DateTime) Format(format string) string { + return DateTimeFormat(dt.time, format) +} + +func (dt DateTime) String() string { + return dt.Format("YYYY-MM-DDTHH:mm:ss.msZ") +} + +func (dt DateTime) SetWeekFormatFunc(format func(week int) string) { + dt.weekFormat = format +} + +func (dt DateTime) SetMonthFormatFunc(format func(month int) string) { + dt.monthFormat = format +} + +func (dt DateTime) MonthToString() string { + if dt.weekFormat == nil { + return dt.time.Month().String() + } + return dt.monthFormat(dt.Month) +} + +func (dt DateTime) WeekToString() string { + if dt.weekFormat == nil { + return dt.time.Weekday().String() + } + return dt.weekFormat(int(dt.WeekDay())) +} + +func (dt DateTime) TimeToString() string { + return dt.Format(dt.TimeFormat) +} + +func (dt DateTime) Today() string { + return dt.Format(dt.DateFormat) +} + +func (dt DateTime) Parse(format string) (DateTime, error) { + d := DateTime{} + parsedTime, err := time.Parse(time.RFC3339, format) + + if err != nil { + return d, err + } + + d.time = parsedTime + d.DateFormat = dt.DateFormat + d.TimeFormat = dt.TimeFormat + d.monthFormat = dt.monthFormat + d.weekFormat = dt.weekFormat + d.Year = d.time.Year() + d.Month = int(d.time.Month()) + d.Day = d.time.Day() + d.Hour = d.time.Hour() + d.Minute = d.time.Minute() + d.Second = d.time.Second() + d.Nanosecond = d.time.Nanosecond() + return d, nil +} + +func (dt DateTime) SetTime(sec int64, ns int64) DateTime { + d := DateTime{ + time: time.Unix(sec, ns), + DateFormat: dt.DateFormat, + TimeFormat: dt.TimeFormat, + monthFormat: dt.monthFormat, + weekFormat: dt.weekFormat, + } + d.Year = d.time.Year() + d.Month = int(d.time.Month()) + d.Day = d.time.Day() + d.Hour = d.time.Hour() + d.Minute = d.time.Minute() + d.Second = d.time.Second() + d.Nanosecond = d.time.Nanosecond() + return d +} + +func (dt DateTime) LocaleCallBack(t string, call func(t string) string) string { + return dt.Format(call(t)) +} + +func (dt DateTime) IsLeapYear() bool { + return ((dt.Year%4 == 0) && (dt.Year%100 != 0)) || (dt.Year%400 == 0) +} + +func (dt DateTime) DayOfYear() int { + return dt.time.YearDay() +} + +func (dt DateTime) MinuteOfDay() int { + return dt.Hour*60 + dt.Minute +} + +func (dt DateTime) CurrentYearDays() int { + days := 365 + if dt.IsLeapYear() { + return days + 1 + } + return days +} + +func (dt DateTime) AddDays(days int) DateTime { + return dt.Add(days, "day") +} + +func (dt DateTime) AddMonth(month int) DateTime { + return dt.Add(month, "month") +} +func (dt DateTime) AddWeek(week int) DateTime { + return dt.Add(week, "week") +} + +func (d DateTime) SubtractDays(days int) DateTime { + return d.AddDays(-days) +} + +func (d DateTime) WeekDay() int { + return int(d.time.Weekday()) +} + +func (d DateTime) WeekOfYear() int { + _, week := d.time.ISOWeek() + return week +} + +func (d DateTime) Add(num int, unit AddUnits) DateTime { + result := DateTime{} + switch unit { + case "Year", "year", "Y": + result = d.SetYear(d.Year+num, d.Month, d.Day, d.Hour, d.Minute, d.Second, d.Nanosecond) + case "month", "M": + result = d.SetMonth(d.Month+num, d.Day, d.Hour, d.Minute, d.Second, d.Nanosecond) + case "day", "D": + result = d.SetDate(d.Day+num, d.Hour, d.Minute, d.Second, d.Nanosecond) + case "week", "W": + result = d.SetDate(d.Day+(num*7), d.Hour, d.Minute, d.Second, d.Nanosecond) + case "hour", "H", "h": + result = d.SetHour(d.Hour+num, d.Minute, d.Second, d.Nanosecond) + case "minute", "m": + result = d.SetMinute(d.Minute+num, d.Second, d.Nanosecond) + case "second", "s": + result = d.SetSecond(d.Second+num, d.Nanosecond) + case "milliseconds", "ms": + result = d.SetMilliseconds(d.Milliseconds+num, d.Nanosecond) + case "nanosecond", "ns": + result = d.SetNanosecond(d.Nanosecond + num) + } + return result +} + +func (dt DateTime) Time() int64 { + return dt.time.UnixNano() +} + +func (dt DateTime) Now() DateTime { + now := time.Now() + return dt.SetTime(now.Unix(), int64(now.Nanosecond())) +} + +func (dt DateTime) UTCOffset() int64 { + localUnix := dt.time.Local().Unix() + utcUnix := dt.time.Unix() + return localUnix - utcUnix +} + +func (dt DateTime) IsToday(date DateTime) bool { + return dt.Year == date.Year && dt.Month == date.Month && dt.Day == date.Day +} + +func (dt DateTime) Max(date ...DateTime) DateTime { + var max DateTime + for _, v := range date { + if max.Time() < v.Time() { + max = v + } + } + return max +} + +func (dt DateTime) Min(date ...DateTime) DateTime { + min := date[0] + for _, v := range date { + if v.Time() > min.Time() { + min = v + } + } + return min +} + +func (dt DateTime) IsBefore(d DateTime) bool { + return d.Time() < dt.Time() +} + +func (dt DateTime) IsAfter(d DateTime) bool { + return dt.Time() < d.Time() +} diff --git a/utils_test.go b/utils_test.go index 2c4074a..8d99b0b 100644 --- a/utils_test.go +++ b/utils_test.go @@ -90,11 +90,10 @@ func TestCookieParse(t *testing.T) { fmt.Printf("%s\n", cookie.ToString()) } -func TestDebounce(t *testing.T){ +func TestDebounce(t *testing.T) { } - func TestgetPathValue(t *testing.T) { result := utils.GetPathValue("/user/:id", "/user/12") if result["id"] != "12" { @@ -270,27 +269,62 @@ func TestNestedAttr(t *testing.T) { } } +func TestDateTimeFormat(t *testing.T) { + datetime := time.Unix(1706572292, 0) + year := utils.DateTimeFormat(datetime, "YYYY") + if year != "2024" { + t.Error("format year is wrong") + } + + result1 := utils.DateTimeFormat(datetime, "YY/MM/dd") + if result1 != "24/01/30" { + t.Error("format date wrong") + } + + result2 := utils.DateTimeFormat(datetime, "MM/dd/YYYY HH:mm:ss") + + if result2 != "01/30/2024 07:51:32" { + t.Error("format datetime wrong") + } + + result3 := utils.DateTimeFormat(datetime, "YYYY年M月d日 H时m分s秒") + if result3 != "2024年1月30日 7时51分32秒" { + t.Error("format has wrong") + } +} + +func TestDateTime(t *testing.T) { + datetime := utils.NewDateTime() + datetime = datetime.SetTime(1706572292,0) -func TestDateTimeFormat(t *testing.T){ - datetime := time.Unix(1706572292,0) - year := utils.DateTimeFormat(datetime,"YYYY") - if year != "2024" { - t.Error("format year is wrong") + if datetime.Day != 30 { + t.Error("the field Day is wrong") } - result1 := utils.DateTimeFormat(datetime,"YY/MM/dd") - if result1 != "24/01/30" { - t.Error("format date wrong") + if datetime.Year != 2024 { + t.Error("the field Day is wrong") } - result2 := utils.DateTimeFormat(datetime,"MM/dd/YYYY HH:mm:ss") + if datetime.Add(2,"year").Year != 2026 { + t.Error("the add 2 year has wrong") + } - if result2 != "01/30/2024 07:51:32"{ - t.Error("format datetime wrong") + if datetime.Add(1,"week").Day != 6 { + t.Error("the add 1 week has wrong") } + fmt.Println(datetime.String()) - result3 := utils.DateTimeFormat(datetime,"YYYY年M月d日 H时m分s秒") - if result3 != "2024年1月30日 7时51分32秒"{ - t.Error("format has wrong") + + if datetime.String() != "2024-01-30T07:51:32.5132Z" { + t.Error("format time has wrong") + } + + if datetime.Add(100,"D").String() != "2024-05-09T07:51:32.5132Z" { + t.Error("add 100 days has wrong") + } + + if datetime.CurrentYearDays() != 366 { + t.Error("caculate has wrong") } + }