gte/internal/task/date.go

275 lines
4.6 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 (
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)"
)
var Today Date
func init() {
year, month, day := time.Now().Date()
Today = NewDate(year, int(month), day)
}
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
}
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":
2021-02-01 07:20:21 +01:00
return Today
2021-02-01 15:34:56 +01:00
case "tomorrow":
2021-02-01 07:20:21 +01:00
return Today.AddDays(1)
2021-02-01 15:34:56 +01:00
case "day after tomorrow":
fallthrough
2021-09-23 06:59:11 +02:00
case "day-after-tomorrow":
2021-02-01 15:34:56 +01:00
return Today.AddDays(2)
case "this week":
fallthrough
2021-09-23 06:59:11 +02:00
case "this-week":
2021-02-01 15:34:56 +01:00
daysToAdd := findDaysToWeekday(Today.Weekday(), time.Friday)
return Today.Add(daysToAdd)
case "next week":
fallthrough
2021-09-23 06:59:11 +02:00
case "next-week":
2021-02-01 15:34:56 +01:00
daysToAdd := findDaysToWeekday(Today.Weekday(), time.Friday) + 7
return Today.Add(daysToAdd)
case "this sprint":
2021-02-09 07:12:21 +01:00
tDate := NewDate(2021, 1, 28) // a sprint end
for {
if tDate.After(Today) {
return tDate
}
tDate = tDate.AddDays(14)
2021-02-01 15:34:56 +01:00
}
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
}
2021-02-01 15:34:56 +01:00
daysToAdd := findDaysToWeekday(Today.Weekday(), newWeekday)
return Today.Add(daysToAdd)
}
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))
}
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
case "tuesday":
return time.Tuesday, true
case "wednesday":
return time.Wednesday, true
case "thursday":
return time.Thursday, true
case "friday":
return time.Friday, true
case "saturday":
return time.Saturday, true
case "sunday":
return time.Sunday, true
case "maandag":
return time.Monday, true
case "dinsdag":
return time.Tuesday, true
case "woensdag":
return time.Wednesday, true
case "donderdag":
return time.Thursday, true
case "vrijdag":
return time.Friday, true
case "zaterdag":
return time.Saturday, true
case "zondag":
return time.Sunday, true
}
return time.Monday, false
}
func lowerAndTrim(str string) string {
return strings.TrimSpace(strings.ToLower(str))
}