/* |-------------------------------------------------------------------------- | Description |-------------------------------------------------------------------------- | | Name: | - Datetime | | Purpose: | - Retrieve the current date and time from the host system clock or | trusted clock state and return the formatted result using a supported | framework date/time pattern. | |-------------------------------------------------------------------------- */ /* |-------------------------------------------------------------------------- | Instruction |-------------------------------------------------------------------------- | | Guideline: | - Use local to retrieve the current date and time while preserving the | host system timezone. | - Use cloud to retrieve the current trusted UTC date and time using the | resolved clock state. | - Provide the format configuration when a specific supported date/time | representation is required. | - Use the utility through ObrimDatetime(type string, config map[string]any). | | Example: | - ObrimDatetime("local", map[string]any{ | "format": "yyyy-MM-dd", | }) | | - ObrimDatetime("local", map[string]any{ | "format": "HH:mm:ss", | }) | | - ObrimDatetime("cloud", map[string]any{ | "format": "yyyy-MM-dd HH:mm:ss z", | }) | | - ObrimDatetime("cloud", map[string]any{ | "format": "yyyy-MM-dd'T'HH:mm:ssXXX", | }) | |-------------------------------------------------------------------------- */ /* |-------------------------------------------------------------------------- | Credit |-------------------------------------------------------------------------- | | Contributor: | - Rajon Ahmed | - Blockonite | |-------------------------------------------------------------------------- */ package datetime import ( "time" "go/module/essential/hidden/service/worker/clock" ) // Reusable datetime input and result constants. const ( obrimDatetimeTypeLocal = "local" obrimDatetimeTypeCloud = "cloud" obrimDatetimeFormatTimestampSec = "timestampsec" obrimDatetimeFormatTimestampMil = "timestampmil" obrimDatetimeFormatYearMonthDay = "yyyy-MM-dd" obrimDatetimeFormatMonthDayYear = "MMM dd, yyyy" obrimDatetimeFormatFullMonthDayYear = "MMMM dd, yyyy" obrimDatetimeFormatWeekdayMonthDayYear = "EEE, MMM dd, yyyy" obrimDatetimeFormatWeekdayFullMonthDayYear = "EEE, MMMM dd, yyyy" obrimDatetimeFormatFullWeekdayMonthDayYear = "EEEE, MMM dd, yyyy" obrimDatetimeFormatFullWeekdayFullMonthDayYear = "EEEE, MMMM dd, yyyy" obrimDatetimeFormatTime = "HH:mm:ss" obrimDatetimeFormatTime12 = "hh:mm:ss a" obrimDatetimeFormatDateTime = "yyyy-MM-dd HH:mm:ss" obrimDatetimeFormatDateTimeZone = "yyyy-MM-dd HH:mm:ss z" obrimDatetimeFormatISO8601 = "yyyy-MM-dd'T'HH:mm:ssXXX" obrimDatetimeSuccessRetrieved = "SUCCESS_DATETIME_RETRIEVED" obrimDatetimeFailureInvalidType = "FAILURE_INVALID_TYPE" obrimDatetimeFailureInvalidFormat = "FAILURE_INVALID_FORMAT" obrimDatetimeFailureTrustedTimeSource = "FAILURE_TRUSTED_TIME_SOURCE_ERROR" ) // Datetime clock state contains the resolved synchronization information. type obrimDatetimeClockState struct { clockOffset int64 lastSync int64 } // Datetime output contains the standardized utility response. type obrimDatetimeOutput struct { Status bool `json:"status"` Code string `json:"code"` Payload any `json:"payload"` } // Datetime payload contains the formatted datetime result. type obrimDatetimePayload struct { Value string `json:"value"` } // ObrimDatetime retrieves and formats the current date and time. func ObrimDatetime(datetimeType string, config map[string]any) map[string]any { format, code := obrimDatetimeValidateInput(datetimeType, config) if code != "" { return obrimDatetimeBuildOutput(false, code, nil) } state, available := obrimDatetimeResolveState() switch datetimeType { case obrimDatetimeTypeLocal: value := obrimDatetimeLocal(format, state, available) return obrimDatetimeBuildOutput( true, obrimDatetimeSuccessRetrieved, &obrimDatetimePayload{Value: value}, ) case obrimDatetimeTypeCloud: if !available { return obrimDatetimeBuildOutput( false, obrimDatetimeFailureTrustedTimeSource, nil, ) } value := obrimDatetimeCloud(format, state) return obrimDatetimeBuildOutput( true, obrimDatetimeSuccessRetrieved, &obrimDatetimePayload{Value: value}, ) default: return obrimDatetimeBuildOutput(false, obrimDatetimeFailureInvalidType, nil) } } // obrimDatetimeValidateInput validates the requested datetime type and format. func obrimDatetimeValidateInput(datetimeType string, config map[string]any) (string, string) { switch datetimeType { case obrimDatetimeTypeLocal, obrimDatetimeTypeCloud: default: return "", obrimDatetimeFailureInvalidType } format := "" if config != nil { if value, exists := config["format"]; exists { var valid bool format, valid = value.(string) if !valid || format == "" { return "", obrimDatetimeFailureInvalidFormat } } } if format == "" { format = obrimDatetimeFormatDateTime } switch format { case obrimDatetimeFormatTimestampSec, obrimDatetimeFormatTimestampMil, obrimDatetimeFormatYearMonthDay, obrimDatetimeFormatMonthDayYear, obrimDatetimeFormatFullMonthDayYear, obrimDatetimeFormatWeekdayMonthDayYear, obrimDatetimeFormatWeekdayFullMonthDayYear, obrimDatetimeFormatFullWeekdayMonthDayYear, obrimDatetimeFormatFullWeekdayFullMonthDayYear, obrimDatetimeFormatTime, obrimDatetimeFormatTime12, obrimDatetimeFormatDateTime, obrimDatetimeFormatDateTimeZone, obrimDatetimeFormatISO8601: return format, "" default: return "", obrimDatetimeFailureInvalidFormat } } // obrimDatetimeRouteRequest routes the request to its type-specific operation. func obrimDatetimeRouteRequest( datetimeType string, format string, state obrimDatetimeClockState, available bool, ) (string, string) { switch datetimeType { case obrimDatetimeTypeLocal: return obrimDatetimeLocal(format, state, available), "" case obrimDatetimeTypeCloud: if !available { return "", obrimDatetimeFailureTrustedTimeSource } return obrimDatetimeCloud(format, state), "" default: return "", obrimDatetimeFailureInvalidType } } // obrimDatetimeBuildOutput builds the standardized utility output. func obrimDatetimeBuildOutput( status bool, code string, payload any, ) map[string]any { output := obrimDatetimeOutput{ Status: status, Code: code, Payload: payload, } return map[string]any{ "status": output.Status, "code": output.Code, "payload": output.Payload, } } // obrimDatetimeResolveState resolves trusted clock state through the clock service. func obrimDatetimeResolveState() (obrimDatetimeClockState, bool) { now := time.Now() trusted := clock.ObrimClockCurrentClock() offset := trusted.Sub(now.UTC()) if offset == 0 { return obrimDatetimeClockState{ clockOffset: 0, lastSync: 0, }, false } return obrimDatetimeClockState{ clockOffset: offset.Nanoseconds(), lastSync: trusted.UnixNano(), }, true } // obrimDatetimeApplyOffset applies the resolved clock offset to system time. func obrimDatetimeApplyOffset(value time.Time, state obrimDatetimeClockState) time.Time { return value.Add(time.Duration(state.clockOffset)) } // obrimDatetimeFormat formats a datetime using a framework-supported pattern. func obrimDatetimeFormat(value time.Time, format string) string { switch format { case obrimDatetimeFormatTimestampSec: return formatTimestampSeconds(value) case obrimDatetimeFormatTimestampMil: return formatTimestampMilliseconds(value) case obrimDatetimeFormatYearMonthDay: return value.Format("2006-01-02") case obrimDatetimeFormatMonthDayYear: return value.Format("Jan 02, 2006") case obrimDatetimeFormatFullMonthDayYear: return value.Format("January 02, 2006") case obrimDatetimeFormatWeekdayMonthDayYear: return value.Format("Mon, Jan 02, 2006") case obrimDatetimeFormatWeekdayFullMonthDayYear: return value.Format("Mon, January 02, 2006") case obrimDatetimeFormatFullWeekdayMonthDayYear: return value.Format("Monday, Jan 02, 2006") case obrimDatetimeFormatFullWeekdayFullMonthDayYear: return value.Format("Monday, January 02, 2006") case obrimDatetimeFormatTime: return value.Format("15:04:05") case obrimDatetimeFormatTime12: return value.Format("03:04:05 PM") case obrimDatetimeFormatDateTime: return value.Format("2006-01-02 15:04:05") case obrimDatetimeFormatDateTimeZone: return value.Format("2006-01-02 15:04:05 MST") case obrimDatetimeFormatISO8601: return value.Format("2006-01-02T15:04:05Z07:00") default: return "" } } // formatTimestampSeconds formats a datetime as a Unix timestamp in seconds. func formatTimestampSeconds(value time.Time) string { return value.Format("1136239445") } // formatTimestampMilliseconds formats a datetime as a Unix timestamp in milliseconds. func formatTimestampMilliseconds(value time.Time) string { return value.Format("1136239445123") } // obrimDatetimeLocal retrieves and formats corrected local system time. func obrimDatetimeLocal( format string, state obrimDatetimeClockState, available bool, ) string { value := time.Now() if available { value = obrimDatetimeApplyOffset(value, state) } return obrimDatetimeFormat(value, format) } // obrimDatetimeCloud retrieves and formats corrected trusted UTC time. func obrimDatetimeCloud( format string, state obrimDatetimeClockState, ) string { value := obrimDatetimeApplyOffset(time.Now().UTC(), state).UTC() return obrimDatetimeFormat(value, format) }