yao/agent/robot/utils/time.go
Max f330a92a2b Enhance Robot Cache Implementation and Documentation
- Marked the Cache Implementation as complete in TODO.md, confirming all tasks are finished with comprehensive integration tests.
- Updated cache.go to provide a thread-safe in-memory cache for Robot instances, improving performance and reliability.
- Enhanced the Load method to include pagination and configurable model name, ensuring efficient data handling.
- Added detailed comments and structured code for better readability and maintainability across the cache implementation.
- Improved validation and error handling in various utility functions to ensure robustness in data processing.
2026-01-14 18:54:18 +08:00

114 lines
2.8 KiB
Go

package utils
import (
"fmt"
"strconv"
"strings"
"time"
)
// ParseTime parses a time string in HH:MM format
func ParseTime(timeStr string) (hour, minute int, err error) {
parts := strings.Split(timeStr, ":")
if len(parts) != 2 {
return 0, 0, fmt.Errorf("invalid time format: %s (expected HH:MM)", timeStr)
}
hour, err = strconv.Atoi(parts[0])
if err != nil || hour < 0 || hour > 23 {
return 0, 0, fmt.Errorf("invalid hour: %s", parts[0])
}
minute, err = strconv.Atoi(parts[1])
if err != nil || minute < 0 || minute > 59 {
return 0, 0, fmt.Errorf("invalid minute: %s", parts[1])
}
return hour, minute, nil
}
// FormatTime formats hour and minute into HH:MM format
func FormatTime(hour, minute int) string {
return fmt.Sprintf("%02d:%02d", hour, minute)
}
// LoadLocation loads a timezone location, returns Local if empty or invalid
func LoadLocation(tz string) *time.Location {
if tz == "" {
return time.Local
}
loc, err := time.LoadLocation(tz)
if err != nil {
return time.Local
}
return loc
}
// ParseDuration parses a duration string with fallback default
func ParseDuration(durStr string, defaultDur time.Duration) time.Duration {
if durStr == "" {
return defaultDur
}
d, err := time.ParseDuration(durStr)
if err != nil {
return defaultDur
}
return d
}
// IsTimeMatch checks if current time matches the specified time (HH:MM)
func IsTimeMatch(now time.Time, timeStr string, loc *time.Location) bool {
hour, minute, err := ParseTime(timeStr)
if err != nil {
return false
}
nowInLoc := now.In(loc)
return nowInLoc.Hour() == hour && nowInLoc.Minute() == minute
}
// IsDayMatch checks if current day matches the specified day
// days can be: "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", or "*" for any day
func IsDayMatch(now time.Time, days []string) bool {
if len(days) == 0 {
return true
}
dayName := now.Weekday().String()[:3] // "Monday" -> "Mon"
for _, day := range days {
if day == "*" || day == dayName {
return true
}
}
return false
}
// NextScheduledTime calculates the next time a scheduled time will occur
func NextScheduledTime(now time.Time, timeStr string, days []string, loc *time.Location) (time.Time, error) {
hour, minute, err := ParseTime(timeStr)
if err != nil {
return time.Time{}, err
}
nowInLoc := now.In(loc)
// Start from today at the specified time
next := time.Date(nowInLoc.Year(), nowInLoc.Month(), nowInLoc.Day(), hour, minute, 0, 0, loc)
// If the time has passed today, start from tomorrow
if next.Before(nowInLoc) || next.Equal(nowInLoc) {
next = next.Add(24 * time.Hour)
}
// Find the next matching day (within 7 days)
for i := 0; i < 7; i++ {
if IsDayMatch(next, days) {
return next, nil
}
next = next.Add(24 * time.Hour)
}
// If no matching day found (should not happen with valid days), return the calculated time
return next, nil
}