gte/internal/task/date.go

280 lines
4.7 KiB
Go
Raw Normal View History

2021-01-29 17:22:07 +01:00
package task
2021-01-30 11:20:12 +01:00
import (
2022-10-23 12:45:21 +02:00
"encoding/json"
2021-01-31 12:11:02 +01:00
"fmt"
2021-02-02 08:47:58 +01:00
"sort"
2021-01-30 15:25:25 +01:00
"strings"
2021-01-30 11:20:12 +01:00
"time"
)
2021-01-29 17:22:07 +01:00
2021-01-30 15:25:25 +01:00
const (
DateFormat = "2006-01-02 (Monday)"
)
2022-06-06 11:07:03 +02:00
func Today() Date {
2021-01-30 15:25:25 +01:00
year, month, day := time.Now().Date()
2022-06-06 11:07:03 +02:00
return NewDate(year, int(month), day)
2021-01-30 15:25:25 +01:00
}
2021-02-02 08:47:58 +01:00
type Weekdays []time.Weekday
func (wds Weekdays) Len() int { return len(wds) }
func (wds Weekdays) Swap(i, j int) { wds[j], wds[i] = wds[i], wds[j] }
func (wds Weekdays) Less(i, j int) bool {
if wds[i] == time.Sunday {
return false
}
if wds[j] == time.Sunday {
return true
}
return int(wds[i]) < int(wds[j])
}
func (wds Weekdays) Unique() Weekdays {
mwds := map[time.Weekday]bool{}
for _, wd := range wds {
mwds[wd] = true
}
newWds := Weekdays{}
for wd := range mwds {
newWds = append(newWds, wd)
}
sort.Sort(newWds)
return newWds
}
2021-01-30 11:20:12 +01:00
type Date struct {
t time.Time
}
2022-10-23 12:45:21 +02:00
func (d *Date) MarshalJSON() ([]byte, error) {
return json.Marshal(d.String())
}
func (d *Date) UnmarshalJSON(data []byte) error {
dateString := ""
if err := json.Unmarshal(data, &dateString); err != nil {
return err
}
nd := NewDateFromString(dateString)
d.t = nd.Time()
return nil
}
2021-01-30 15:25:25 +01:00
func NewDate(year, month, day int) Date {
2021-03-03 11:54:36 +01:00
if year == 0 || month == 0 || month > 12 || day == 0 {
2021-01-30 15:25:25 +01:00
return Date{}
}
2021-01-30 11:20:12 +01:00
var m time.Month
switch month {
case 1:
m = time.January
case 2:
m = time.February
case 3:
m = time.March
case 4:
m = time.April
case 5:
m = time.May
case 6:
m = time.June
case 7:
m = time.July
case 8:
m = time.August
case 9:
m = time.September
case 10:
m = time.October
case 11:
m = time.November
case 12:
m = time.December
}
2021-01-30 15:25:25 +01:00
t := time.Date(year, m, day, 0, 0, 0, 0, time.UTC)
2021-01-30 11:20:12 +01:00
2021-01-30 15:25:25 +01:00
return Date{
t: t,
2021-01-30 11:20:12 +01:00
}
2021-01-30 15:25:25 +01:00
}
2021-01-30 11:20:12 +01:00
2021-01-30 15:25:25 +01:00
func NewDateFromString(date string) Date {
date = strings.ToLower(strings.TrimSpace(date))
2021-02-01 15:34:56 +01:00
switch date {
case "":
fallthrough
2021-09-23 06:59:11 +02:00
case "no-date":
fallthrough
2021-02-01 15:34:56 +01:00
case "no date":
2021-01-30 15:25:25 +01:00
return Date{}
2021-02-01 15:34:56 +01:00
case "today":
2022-06-06 11:07:03 +02:00
return Today()
2022-10-25 16:06:09 +02:00
case "tod":
return Today()
2021-02-01 15:34:56 +01:00
case "tomorrow":
2022-06-06 11:07:03 +02:00
return Today().AddDays(1)
2022-10-25 16:06:09 +02:00
case "tom":
return Today().AddDays(1)
2021-02-01 07:20:21 +01:00
}
2021-01-31 12:11:02 +01:00
t, err := time.Parse("2006-01-02", fmt.Sprintf("%.10s", date))
2021-01-30 15:25:25 +01:00
if err == nil {
return Date{t: t}
}
2021-02-01 07:20:21 +01:00
newWeekday, ok := ParseWeekday(date)
if !ok {
return Date{}
2021-01-30 15:25:25 +01:00
}
2022-06-06 11:07:03 +02:00
daysToAdd := findDaysToWeekday(Today().Weekday(), newWeekday)
2021-02-01 15:34:56 +01:00
2022-06-06 11:07:03 +02:00
return Today().Add(daysToAdd)
2021-02-01 15:34:56 +01:00
}
func findDaysToWeekday(current, wanted time.Weekday) int {
daysToAdd := int(wanted) - int(current)
2021-01-31 08:22:31 +01:00
if daysToAdd <= 0 {
2021-01-30 15:25:25 +01:00
daysToAdd += 7
}
2021-02-01 15:34:56 +01:00
return daysToAdd
}
func (d Date) DaysBetween(d2 Date) int {
tDate := d2
end := d
if !end.After(tDate) {
end = d2
tDate = d
}
days := 0
for {
if tDate.Add(days).Equal(end) {
return days
}
days++
}
2021-01-30 11:20:12 +01:00
}
2021-02-01 15:34:56 +01:00
func (d Date) String() string {
2021-01-30 11:20:12 +01:00
if d.t.IsZero() {
return "no date"
}
2021-01-29 17:22:07 +01:00
2021-01-30 15:25:25 +01:00
return strings.ToLower(d.t.Format(DateFormat))
}
2022-06-05 14:37:50 +02:00
func (d Date) Human() string {
2022-06-06 10:21:26 +02:00
switch {
case d.IsZero():
2022-06-05 14:37:50 +02:00
return "-"
2022-06-06 11:07:03 +02:00
case d.Equal(Today()):
2022-06-06 10:21:26 +02:00
return "today"
2022-06-06 11:07:03 +02:00
case d.Equal(Today().Add(1)):
2022-06-06 10:21:26 +02:00
return "tomorrow"
2022-06-06 11:07:03 +02:00
case d.After(Today()) && Today().Add(8).After(d):
2022-06-05 14:37:50 +02:00
return strings.ToLower(d.t.Format("Monday"))
2022-06-06 10:21:26 +02:00
default:
return strings.ToLower(d.t.Format(DateFormat))
2022-06-05 14:37:50 +02:00
}
}
2021-02-01 15:34:56 +01:00
func (d Date) IsZero() bool {
2021-01-30 15:25:25 +01:00
return d.t.IsZero()
}
2021-02-01 15:34:56 +01:00
func (d Date) Time() time.Time {
2021-01-31 10:01:03 +01:00
return d.t
}
2021-02-01 15:34:56 +01:00
func (d Date) Weekday() time.Weekday {
2021-01-31 10:01:03 +01:00
return d.t.Weekday()
2021-01-30 15:25:25 +01:00
}
2021-02-03 10:25:25 +01:00
func (d Date) Day() int {
return d.t.Day()
}
2021-02-01 15:34:56 +01:00
func (d Date) Add(days int) Date {
2021-01-30 15:25:25 +01:00
year, month, day := d.t.Date()
return NewDate(year, int(month), day+days)
2021-01-29 17:22:07 +01:00
}
2021-01-31 10:01:03 +01:00
2021-03-03 11:54:36 +01:00
func (d Date) AddMonths(addMonths int) Date {
2021-10-31 09:52:43 +01:00
year, mmonth, day := d.t.Date()
month := int(mmonth)
for m := 1; m <= addMonths; m++ {
month += 1
if month == 12 {
year += 1
month = 1
}
}
2021-03-03 11:54:36 +01:00
2021-10-31 09:52:43 +01:00
return NewDate(year, month, day)
2021-03-03 11:54:36 +01:00
}
2021-02-01 15:34:56 +01:00
func (d Date) Equal(ud Date) bool {
2021-01-31 12:11:02 +01:00
return d.t.Equal(ud.Time())
}
// After reports whether d is after ud
2021-02-01 15:34:56 +01:00
func (d Date) After(ud Date) bool {
2021-01-31 10:01:03 +01:00
return d.t.After(ud.Time())
}
2021-01-31 12:11:02 +01:00
2021-02-01 15:34:56 +01:00
func (d Date) AddDays(amount int) Date {
2021-01-31 12:11:02 +01:00
year, month, date := d.t.Date()
return NewDate(year, int(month), date+amount)
}
func ParseWeekday(wd string) (time.Weekday, bool) {
switch lowerAndTrim(wd) {
case "monday":
return time.Monday, true
2022-10-25 16:06:09 +02:00
case "mon":
return time.Monday, true
2021-01-31 12:11:02 +01:00
case "tuesday":
return time.Tuesday, true
2022-10-25 16:06:09 +02:00
case "tue":
return time.Tuesday, true
2021-01-31 12:11:02 +01:00
case "wednesday":
return time.Wednesday, true
2022-10-25 16:06:09 +02:00
case "wed":
return time.Wednesday, true
2021-01-31 12:11:02 +01:00
case "thursday":
return time.Thursday, true
2022-10-25 16:06:09 +02:00
case "thu":
return time.Thursday, true
2021-01-31 12:11:02 +01:00
case "friday":
return time.Friday, true
2022-10-25 16:06:09 +02:00
case "fri":
return time.Friday, true
2021-01-31 12:11:02 +01:00
case "saturday":
return time.Saturday, true
2022-10-25 16:06:09 +02:00
case "sat":
return time.Saturday, true
2021-01-31 12:11:02 +01:00
case "sunday":
return time.Sunday, true
2022-10-25 16:06:09 +02:00
case "sun":
2021-01-31 12:11:02 +01:00
return time.Sunday, true
2022-10-25 16:06:09 +02:00
default:
return time.Monday, false
2021-01-31 12:11:02 +01:00
}
}
func lowerAndTrim(str string) string {
return strings.TrimSpace(strings.ToLower(str))
}