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) }