106 lines
2.6 KiB
Go

package dashboard
import (
"fmt"
"time"
)
func PeriodWindows(eventTime time.Time, statZone *time.Location) []PeriodWindow {
localDate := startOfDay(timeInLocation(eventTime, statZone))
dayEnd := localDate.AddDate(0, 0, 1)
weekday := int(localDate.Weekday())
if weekday == 0 {
weekday = 7
}
weekStart := localDate.AddDate(0, 0, -(weekday - 1))
weekEnd := weekStart.AddDate(0, 0, 7)
monthStart := time.Date(localDate.Year(), localDate.Month(), 1, 0, 0, 0, 0, statZone)
monthEnd := monthStart.AddDate(0, 1, 0)
_, isoWeek := localDate.ISOWeek()
isoYear, _ := localDate.ISOWeek()
return []PeriodWindow{
{
Type: PeriodDay,
Key: localDate.Format("2006-01-02"),
Name: localDate.Format("2006-01-02"),
StartDate: ptrTime(localDate),
EndDate: ptrTime(dayEnd),
},
{
Type: PeriodWeek,
Key: fmt.Sprintf("%04d-W%02d", isoYear, isoWeek),
Name: fmt.Sprintf("%04d-W%02d", isoYear, isoWeek),
StartDate: ptrTime(weekStart),
EndDate: ptrTime(weekEnd),
},
{
Type: PeriodMonth,
Key: localDate.Format("2006-01"),
Name: localDate.Format("2006-01"),
StartDate: ptrTime(monthStart),
EndDate: ptrTime(monthEnd),
},
{
Type: PeriodAll,
Key: PeriodAll,
Name: "全部",
},
}
}
func SamePeriod(left time.Time, right time.Time, window PeriodWindow, statZone *time.Location) bool {
if left.IsZero() || right.IsZero() {
return false
}
if window.Type == PeriodAll {
return true
}
leftLocal := timeInLocation(left, statZone)
rightLocal := timeInLocation(right, statZone)
switch window.Type {
case PeriodDay:
return startOfDay(leftLocal).Equal(startOfDay(rightLocal))
case PeriodWeek:
leftYear, leftWeek := leftLocal.ISOWeek()
rightYear, rightWeek := rightLocal.ISOWeek()
return leftYear == rightYear && leftWeek == rightWeek
case PeriodMonth:
return leftLocal.Year() == rightLocal.Year() && leftLocal.Month() == rightLocal.Month()
default:
return false
}
}
func DailyDate(eventTime time.Time, storageZone *time.Location) time.Time {
return startOfDay(timeInLocation(eventTime, storageZone))
}
func DateNumber(day time.Time) int {
year, month, date := day.Date()
return year*10000 + int(month)*100 + date
}
func ptrTime(value time.Time) *time.Time {
v := value
return &v
}
func startOfDay(value time.Time) time.Time {
year, month, date := value.Date()
return time.Date(year, month, date, 0, 0, 0, 0, value.Location())
}
func timeInLocation(value time.Time, location *time.Location) time.Time {
if value.IsZero() {
return value
}
if location == nil {
location = time.UTC
}
return value.In(location)
}