Documentation
¶
Overview ¶
Package extclock provides extended-hour clocks and business-day date/time handling.
An extended-hour clock can represent values beyond 24:00, such as 26:30 or 30:00. This is useful when a business day starts at a cutoff hour instead of midnight. With the default cutoff hour of 6, wall-clock time 2026-07-05 02:30 is represented as business date 2026-07-04 with clock 26:30.
Core model ¶
The package has four central value concepts:
- Clock is a date-less extended-hour clock value. It has no date and no timezone.
- Date is a calendar date without clock or timezone information.
- DateTime is a business date paired with an extended-hour clock.
- System owns cutoff-hour-specific validation and conversion rules.
Clock and DateTime clock validity depends on a System. Date validity is calendar-based and independent of cutoff-hour rules. Package-level constructors, parsers, converters, and validators use DefaultSystem. Use System methods when custom cutoff-hour rules or system-specific validation are required.
Default and custom systems ¶
DefaultSystem uses cutoff hour 6, so its maximum clock value is 30:00:00. For any System, MaxHour is 24 + CutoffHour. A custom system can use another supported cutoff hour, such as 0 for a 24:00 maximum or 10 for a 34:00 maximum.
Parsing, formatting, and encoding ¶
Clock, Date, and DateTime support parsing and formatting through explicit layouts and auto layouts. Auto layouts infer supported input shapes; detailed layout behavior is documented on ClockLayout, DateLayout, and DateTimeLayout.
Text and JSON encoding use string forms. Unmarshaling Clock and DateTime values is not a substitute for system-specific validation when custom system rules matter; call System.ValidateClock or System.ValidateDateTime after decoding when necessary.
Business-day conversion ¶
System.FromTime converts wall-clock time.Time values to business DateTime values. System.ToTime converts business DateTime values back to wall-clock time.Time values. System.DayRange and System.DayRangeDate return the half-open wall-clock range [start, end) for a business date.
Duration arithmetic ¶
Clock bounded operations reject results outside the representable clock range. Clock shift operations may cross that range and return a dayOffset. DateTime duration operations can return a new business DateTime directly, while bounded DateTime duration operations reject crossing the business-day boundary.
Comparison semantics ¶
DateTime.Compare performs lexicographic comparison by stored business date and clock. System.CompareDateTime performs system-aware comparison by normalized wall-clock instant. For example, under the default system, 2026-07-04 30:00 and 2026-07-05 06:00 may represent the same wall-clock instant, so pure value comparison and system-aware comparison can differ.
Errors ¶
The package uses exported sentinel errors for parse, validation, layout, and range failures. Callers should use errors.Is to test error categories and should not treat exact error strings as an API contract.
Caveats ¶
Clock has no date or timezone. DateTime is a business representation and is not always a unique normalized wall-clock instant without a System. Timezone and daylight-saving behavior follows the time.Location passed to conversion methods and Go's time package. Very large date differences may exceed time.Duration when using APIs that return durations.
Example (ComparisonSemantics) ¶
package main
import (
"fmt"
"log"
"github.com/Chiyoshic/go-extclock"
)
func main() {
s := extclock.DefaultSystem()
a := s.MustDateTime(extclock.MustDate(2026, 7, 4), s.MustClock(30, 0, 0, 0))
b := s.MustDateTime(extclock.MustDate(2026, 7, 5), s.MustClock(6, 0, 0, 0))
fmt.Println(a.Compare(b) == 0)
n, err := s.CompareDateTime(a, b)
if err != nil {
log.Fatal(err)
}
fmt.Println(n == 0)
}
Output: false true
Example (CustomSystem) ¶
package main
import (
"fmt"
"log"
"time"
"github.com/Chiyoshic/go-extclock"
)
func main() {
cfg, err := extclock.NewConfig(10)
if err != nil {
log.Fatal(err)
}
s, err := extclock.NewSystem(cfg)
if err != nil {
log.Fatal(err)
}
clock, err := s.ParseClock("33:30")
if err != nil {
log.Fatal(err)
}
dt, err := s.NewDateTime(extclock.MustDate(2026, time.July, 4), clock)
if err != nil {
log.Fatal(err)
}
if err := s.ValidateDateTime(dt); err != nil {
log.Fatal(err)
}
fmt.Println(s.MaxHour())
fmt.Println(dt.StringHM())
}
Output: 34 2026-07-04 33:30
Example (QuickStart) ¶
package main
import (
"fmt"
"log"
"time"
"github.com/Chiyoshic/go-extclock"
)
func main() {
clock, err := extclock.ParseClock("26:30")
if err != nil {
log.Fatal(err)
}
dt, err := extclock.ParseDateTime("2026-07-04 26:30")
if err != nil {
log.Fatal(err)
}
wall := time.Date(2026, time.July, 5, 2, 30, 0, 0, time.UTC)
business, err := extclock.FromTime(wall)
if err != nil {
log.Fatal(err)
}
back, err := extclock.DefaultSystem().ToTime(dt, time.UTC)
if err != nil {
log.Fatal(err)
}
fmt.Println(clock.StringHM())
fmt.Println(business.StringHM())
fmt.Println(back.Format(time.RFC3339))
}
Output: 26:30 2026-07-04 26:30 2026-07-05T02:30:00Z
Index ¶
- Constants
- Variables
- func DayRange(year int, month time.Month, day int, loc *time.Location) (start, end time.Time, err error)
- func DayRangeDate(date Date, loc *time.Location) (start, end time.Time, err error)
- func FormatClock(c Clock, layout ClockLayout) (string, error)
- func FormatDate(d Date, layout DateLayout) (string, error)
- func FormatDateTime(dt DateTime, layout DateTimeLayout) (string, error)
- type Clock
- func ClockFromDuration(d time.Duration) (Clock, error)
- func MustClock(hour, minute, second, nanosecond int) Clock
- func MustParseClock(input string) Clock
- func MustParseClockLayout(layout ClockLayout, input string) Clock
- func NewClock(hour, minute, second, nanosecond int) (Clock, error)
- func NewClockHM(hour, minute int) (Clock, error)
- func NewClockHMS(hour, minute, second int) (Clock, error)
- func ParseClock(input string) (Clock, error)
- func ParseClockLayout(layout ClockLayout, input string) (Clock, error)
- func (c Clock) After(other Clock) bool
- func (c Clock) Before(other Clock) bool
- func (c Clock) Compare(other Clock) int
- func (c Clock) Components() (hour, minute, second, nanosecond int)
- func (c Clock) Duration() time.Duration
- func (c Clock) Equal(other Clock) bool
- func (c Clock) Format(layout ClockLayout) (string, error)
- func (c Clock) Hour() int
- func (c Clock) IsExtended() bool
- func (c Clock) IsWholeHour() bool
- func (c Clock) IsZero() bool
- func (c Clock) MarshalJSON() ([]byte, error)
- func (c Clock) MarshalText() ([]byte, error)
- func (c Clock) Minute() int
- func (c Clock) Nanosecond() int
- func (c Clock) Second() int
- func (c Clock) String() string
- func (c Clock) StringHM() string
- func (c Clock) StringHMS() string
- func (c Clock) StringNano() string
- func (c *Clock) UnmarshalJSON(data []byte) error
- func (c *Clock) UnmarshalText(data []byte) error
- type ClockLayout
- type Config
- type Date
- func DateFromTime(t time.Time) (Date, error)
- func MustDate(year int, month time.Month, day int) Date
- func MustDateFromTime(t time.Time) Date
- func MustParseDate(input string) Date
- func MustParseDateLayout(layout DateLayout, input string) Date
- func NewDate(year int, month time.Month, day int) (Date, error)
- func ParseDate(input string) (Date, error)
- func ParseDateLayout(layout DateLayout, input string) (Date, error)
- func (d Date) AddDays(days int) (Date, error)
- func (d Date) After(other Date) bool
- func (d Date) Before(other Date) bool
- func (d Date) Compare(other Date) int
- func (d Date) Components() (year int, month time.Month, day int)
- func (d Date) Day() int
- func (d Date) Equal(other Date) bool
- func (d Date) Format(layout DateLayout) (string, error)
- func (d Date) MarshalJSON() ([]byte, error)
- func (d Date) MarshalText() ([]byte, error)
- func (d Date) Month() time.Month
- func (d Date) MustAddDays(days int) Date
- func (d Date) String() string
- func (d Date) ToTime(loc *time.Location) time.Time
- func (d *Date) UnmarshalJSON(data []byte) error
- func (d *Date) UnmarshalText(data []byte) error
- func (d Date) Valid() bool
- func (d Date) Validate() error
- func (d Date) Year() int
- type DateLayout
- type DateTime
- func FromTime(t time.Time) (DateTime, error)
- func MustDateTime(date Date, clock Clock) DateTime
- func MustParseDateTime(input string) DateTime
- func MustParseDateTimeLayout(layout DateTimeLayout, input string) DateTime
- func NewDateTime(date Date, clock Clock) (DateTime, error)
- func ParseDateTime(input string) (DateTime, error)
- func ParseDateTimeLayout(layout DateTimeLayout, input string) (DateTime, error)
- func (dt DateTime) After(other DateTime) bool
- func (dt DateTime) Before(other DateTime) bool
- func (dt DateTime) Clock() Clock
- func (dt DateTime) Compare(other DateTime) int
- func (dt DateTime) Components() (date Date, clock Clock)
- func (dt DateTime) Date() Date
- func (dt DateTime) Day() int
- func (dt DateTime) Equal(other DateTime) bool
- func (dt DateTime) Format(layout DateTimeLayout) (string, error)
- func (dt DateTime) Hour() int
- func (dt DateTime) MarshalJSON() ([]byte, error)
- func (dt DateTime) MarshalText() ([]byte, error)
- func (dt DateTime) Minute() int
- func (dt DateTime) Month() time.Month
- func (dt DateTime) Nanosecond() int
- func (dt DateTime) Second() int
- func (dt DateTime) String() string
- func (dt DateTime) StringHM() string
- func (dt DateTime) StringHMS() string
- func (dt DateTime) StringNano() string
- func (dt *DateTime) UnmarshalJSON(data []byte) error
- func (dt *DateTime) UnmarshalText(data []byte) error
- func (dt DateTime) Year() int
- type DateTimeLayout
- type ParseError
- type System
- func (s System) AddClockDurationBounded(c Clock, d time.Duration) (Clock, error)
- func (s System) AddDateTime(dt DateTime, d time.Duration) (DateTime, error)
- func (s System) AddDateTimeDuration(dt DateTime, d time.Duration) (DateTime, error)
- func (s System) AddDateTimeDurationBounded(dt DateTime, d time.Duration) (DateTime, error)
- func (s System) AfterClock(a, b Clock) (bool, error)
- func (s System) AfterDateTime(a, b DateTime) (bool, error)
- func (s System) BeforeClock(a, b Clock) (bool, error)
- func (s System) BeforeDateTime(a, b DateTime) (bool, error)
- func (s System) ClockFromDuration(d time.Duration) (Clock, error)
- func (s System) CompareClock(a, b Clock) (int, error)
- func (s System) CompareDateTime(a, b DateTime) (int, error)
- func (s System) Config() Config
- func (s System) CutoffHour() int
- func (s System) DayRange(year int, month time.Month, day int, loc *time.Location) (start, end time.Time, err error)
- func (s System) DayRangeDate(date Date, loc *time.Location) (start, end time.Time, err error)
- func (s System) EqualClock(a, b Clock) (bool, error)
- func (s System) EqualDateTime(a, b DateTime) (bool, error)
- func (s System) FormatClock(c Clock, layout ClockLayout) (string, error)
- func (s System) FormatDateTime(dt DateTime, layout DateTimeLayout) (string, error)
- func (s System) FromTime(t time.Time) (DateTime, error)
- func (s System) IsMaxClock(c Clock) bool
- func (s System) MaxHour() int
- func (s System) MustClock(hour, minute, second, nanosecond int) Clock
- func (s System) MustDateTime(date Date, clock Clock) DateTime
- func (s System) MustParseClock(input string) Clock
- func (s System) MustParseClockLayout(layout ClockLayout, input string) Clock
- func (s System) MustParseDateTime(input string) DateTime
- func (s System) MustParseDateTimeLayout(layout DateTimeLayout, input string) DateTime
- func (s System) NewClock(hour, minute, second, nanosecond int) (Clock, error)
- func (s System) NewClockHM(hour, minute int) (Clock, error)
- func (s System) NewClockHMS(hour, minute, second int) (Clock, error)
- func (s System) NewDateTime(date Date, clock Clock) (DateTime, error)
- func (s System) ParseClock(input string) (Clock, error)
- func (s System) ParseClockLayout(layout ClockLayout, input string) (Clock, error)
- func (s System) ParseDateTime(input string) (DateTime, error)
- func (s System) ParseDateTimeLayout(layout DateTimeLayout, input string) (DateTime, error)
- func (s System) ShiftClockDuration(c Clock, d time.Duration) (clock Clock, dayOffset int, err error)
- func (s System) SubClock(a, b Clock) (time.Duration, error)
- func (s System) SubClockDurationBounded(c Clock, d time.Duration) (Clock, error)
- func (s System) SubDateTime(a, b DateTime) (time.Duration, error)
- func (s System) SubDateTimeDuration(dt DateTime, d time.Duration) (DateTime, error)
- func (s System) SubDateTimeDurationBounded(dt DateTime, d time.Duration) (DateTime, error)
- func (s System) ToTime(dt DateTime, loc *time.Location) (time.Time, error)
- func (s System) UnshiftClockDuration(c Clock, d time.Duration) (clock Clock, dayOffset int, err error)
- func (s System) ValidClock(c Clock) bool
- func (s System) ValidDateTime(dt DateTime) bool
- func (s System) ValidateClock(c Clock) error
- func (s System) ValidateDateTime(dt DateTime) error
Examples ¶
Constants ¶
const ( // DefaultCutoffHour is the cutoff hour used by the default system. DefaultCutoffHour = 6 // MinCutoffHour is the smallest supported cutoff hour. MinCutoffHour = 0 // MaxCutoffHour is the largest supported cutoff hour. MaxCutoffHour = 10 // MinClockHour is the smallest valid hour value for an extended-hour clock. MinClockHour = 0 // DefaultMaxClockHour is the largest clock hour allowed by the default system. DefaultMaxClockHour = 24 + DefaultCutoffHour )
const ( // MinDateYear is the smallest supported calendar year. MinDateYear = 1 // MaxDateYear is the largest supported calendar year. MaxDateYear = 9999 )
Variables ¶
var ( // ErrInvalidConfig reports an unsupported System configuration. ErrInvalidConfig = errors.New("extclock: invalid config") // ErrInvalidClock reports an invalid Clock for the relevant System. ErrInvalidClock = errors.New("extclock: invalid clock") // ErrInvalidDate reports an invalid Date. ErrInvalidDate = errors.New("extclock: invalid date") // ErrInvalidDateTime reports an invalid DateTime or failed DateTime normalization. ErrInvalidDateTime = errors.New("extclock: invalid datetime") // ErrInvalidLayout reports an unsupported parse or format layout. ErrInvalidLayout = errors.New("extclock: invalid layout") // ErrParseClock reports a Clock parsing failure. ErrParseClock = errors.New("extclock: parse clock") // ErrParseDate reports a Date parsing failure. ErrParseDate = errors.New("extclock: parse date") // ErrParseDateTime reports a DateTime parsing failure. ErrParseDateTime = errors.New("extclock: parse datetime") // ErrOutOfRange reports a value outside a supported range. ErrOutOfRange = errors.New("extclock: out of range") )
Functions ¶
func DayRange ¶
func DayRange(year int, month time.Month, day int, loc *time.Location) (start, end time.Time, err error)
DayRange returns the half-open wall-clock time range for a business date under the default system.
With the default cutoff hour of 6, business date 2026-07-04 maps to [2026-07-04 06:00, 2026-07-05 06:00). For custom systems, use System.DayRange.
func DayRangeDate ¶
DayRangeDate returns the half-open wall-clock time range for a business date under the default system.
With the default cutoff hour of 6, business date 2026-07-04 maps to [2026-07-04 06:00, 2026-07-05 06:00). For custom systems, use System.DayRangeDate.
func FormatClock ¶
func FormatClock(c Clock, layout ClockLayout) (string, error)
FormatClock validates c under the default system and formats it with layout.
Unlike Clock.Format, FormatClock checks that c is valid under the default system before formatting. For custom systems, use System.FormatClock.
func FormatDate ¶
func FormatDate(d Date, layout DateLayout) (string, error)
FormatDate returns a string representation of d using layout.
It is equivalent to d.Format(layout).
func FormatDateTime ¶
func FormatDateTime(dt DateTime, layout DateTimeLayout) (string, error)
FormatDateTime validates dt under the default system and formats it with layout.
Unlike DateTime.Format, FormatDateTime checks that dt is valid under the default system before formatting. For custom systems, use System.FormatDateTime.
Types ¶
type Clock ¶
type Clock struct {
// contains filtered or unexported fields
}
Clock represents a date-less extended-hour clock value.
Clock has no date, timezone, or system configuration. Its validity depends on the System used for system-specific validation.
The default System allows:
00:00:00.000000000 <= Clock <= 30:00:00.000000000
A custom System may allow a different maximum, such as 24:00 or 34:00.
func ClockFromDuration ¶
ClockFromDuration converts a duration to a Clock using the default system.
For example, 26h30m becomes 26:30:00 and 30h becomes 30:00:00. Durations greater than 30:00:00 return ErrOutOfRange. For custom systems, use System.ClockFromDuration.
func MustClock ¶
MustClock returns a Clock with the given components using the default system.
It panics if the components are invalid. Intended for tests, constants, and example code. For custom systems, use System.MustClock.
func MustParseClock ¶
MustParseClock parses input as a Clock using the default system.
It panics if parsing fails. Intended for tests, constants, and example code.
func MustParseClockLayout ¶
func MustParseClockLayout(layout ClockLayout, input string) Clock
MustParseClockLayout parses input as a Clock using the default system and layout.
It panics if parsing fails. Intended for tests, constants, and example code.
func NewClock ¶
NewClock returns a Clock with the given components using the default system.
The default system allows clocks up to 30:00:00. For custom systems, use System.NewClock.
func NewClockHM ¶
NewClockHM returns a Clock with hour and minute precision (HH:MM) using the default system. For custom systems, use System.NewClockHM.
func NewClockHMS ¶
NewClockHMS returns a Clock with hour, minute, and second precision (HH:MM:SS) using the default system. For custom systems, use System.NewClockHMS.
func ParseClock ¶
ParseClock parses input as a Clock using the default system and auto-detected layout.
It is equivalent to DefaultSystem().ParseClock(input). For custom systems, use System.ParseClock.
func ParseClockLayout ¶
func ParseClockLayout(layout ClockLayout, input string) (Clock, error)
ParseClockLayout parses input as a Clock using the default system and layout.
It is equivalent to DefaultSystem().ParseClockLayout(layout, input). For custom systems, use System.ParseClockLayout.
func (Clock) After ¶
After reports whether c is later than other.
After does not validate either clock against a System.
func (Clock) Before ¶
Before reports whether c is earlier than other.
Before does not validate either clock against a System.
func (Clock) Compare ¶
Compare compares c and other by elapsed time since Clock 00:00.
It returns -1 if c is before other, 1 if c is after other, and 0 if equal. Compare does not validate either clock against a System; it compares the stored field values only.
func (Clock) Components ¶
Components returns the hour, minute, second, and nanosecond of c.
func (Clock) Duration ¶
Duration returns the elapsed time since Clock 00:00:00.000000000.
Example:
26:30:00 -> 26h30m0s
func (Clock) Equal ¶
Equal reports whether c and other represent the same clock value.
Equal does not validate either clock against a System.
func (Clock) Format ¶
func (c Clock) Format(layout ClockLayout) (string, error)
Format returns a string representation of c using layout.
Supported layouts are ClockLayoutAuto, ClockLayoutHM, ClockLayoutHMS, and ClockLayoutNano. ClockLayoutAuto selects HM, HMS, or Nano based on which components are non-zero. An unknown layout returns ErrInvalidLayout.
Format uses fixed-width fields. For example, hour 6 is written as 06, and fractional seconds are written with 9 digits. Format does not validate c against a System; use System.FormatClock when system-specific validation is required.
func (Clock) Hour ¶
Hour returns the hour component of c.
The hour is a zero-based count from midnight and may exceed 23 on an extended clock. For example, 25:30:00 has hour 25. The returned value is always non-negative for a valid Clock.
func (Clock) IsExtended ¶
IsExtended reports whether c is at or after 24:00:00.
For example, 25:30:00 and 30:00:00 are extended; 23:59:59 is not. In a 24-hour system, 24:00:00 is also considered extended.
func (Clock) IsWholeHour ¶
IsWholeHour reports whether c is on an exact hour with no sub-hour components.
func (Clock) MarshalJSON ¶
MarshalJSON encodes c as a JSON string, for example "26:30:00".
func (Clock) MarshalText ¶
MarshalText encodes c as text using String format.
MarshalText does not validate c against a specific System.
func (Clock) Minute ¶
Minute returns the minute component of c.
The minute is in the range 0–59. It is the minute-of-hour field, not total minutes since midnight.
func (Clock) Nanosecond ¶
Nanosecond returns the sub-second component of c.
The nanosecond is in the range 0–999_999_999. It is the fractional part of the current second, not total nanoseconds since midnight.
func (Clock) Second ¶
Second returns the second component of c.
The second is in the range 0–59. It is the second-of-minute field, not total seconds since midnight.
func (Clock) StringNano ¶
StringNano returns the clock in HH:MM:SS.NNNNNNNNN form with a fixed 9-digit fractional second, for example 26:30:00.120000000.
func (*Clock) UnmarshalJSON ¶
UnmarshalJSON decodes c from a JSON string.
It delegates to UnmarshalText, so it accepts the same library-supported clock range and does not perform system-specific validation.
func (*Clock) UnmarshalText ¶
UnmarshalText decodes c from text within the library-supported clock range.
Parsing uses the same lenient field rules as ParseClockLayout. UnmarshalText does not validate c against a specific System. Use System.ValidateClock after decoding when system-specific validation is required.
type ClockLayout ¶
type ClockLayout string
ClockLayout selects the format used to parse and format Clock values.
Layout names use HH, MM, SS, and NNNNNNNNN as formatting conventions. Parsing is more lenient than formatting:
- fields are colon-separated decimal integers
- hour may use one or more digits, such as 6, 06, or 26
- minute and second accept values in 0..59 without requiring leading zeros
- fractional seconds accept 1 to 9 digits; shorter fractions are padded with trailing zeros during parsing
Formatting uses fixed-width fields. For example, 6:30 is formatted as 06:30, and 26:30:00.12 is formatted as 26:30:00.120000000.
Supported layouts:
ClockLayoutAuto -> auto-detect from ".", ":" count, and field shape ClockLayoutHM -> hour and minute ClockLayoutHMS -> hour, minute, and second ClockLayoutNano -> hour, minute, second, and fractional second
const ( // ClockLayoutAuto selects the clock format automatically when parsing and // selects precision from non-zero components when formatting. ClockLayoutAuto ClockLayout = "" // ClockLayoutHM formats a clock as HH:MM, for example 06:30. // Parsing accepts lenient hour and minute fields, such as 6:30 or 26:5. ClockLayoutHM ClockLayout = "HH:MM" // ClockLayoutHMS formats a clock as HH:MM:SS, for example 26:30:00. // Parsing accepts lenient numeric fields, such as 26:30:0. ClockLayoutHMS ClockLayout = "HH:MM:SS" // ClockLayoutNano formats a clock as HH:MM:SS.NNNNNNNNN, // for example 26:30:00.120000000. Parsing accepts 1 to 9 fractional // digits, such as 26:30:00.12. ClockLayoutNano ClockLayout = "HH:MM:SS.NNNNNNNNN" )
type Config ¶
type Config struct {
// contains filtered or unexported fields
}
Config defines how many hours after midnight still belong to the previous business day.
Examples:
cutoffHour = 0 -> max clock is 24:00 cutoffHour = 6 -> max clock is 30:00 cutoffHour = 10 -> max clock is 34:00
The zero value is valid and means cutoffHour = 0. Use DefaultConfig or NewConfig(-1) to use DefaultCutoffHour.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns the configuration used by DefaultSystem.
func MustConfig ¶
MustConfig returns a Config with the given cutoff hour.
It panics if NewConfig would return an error.
func NewConfig ¶
NewConfig returns a Config with the given cutoff hour.
The cutoff hour must be in [MinCutoffHour, MaxCutoffHour]. Passing -1 is a shorthand for DefaultConfig.
func (Config) CutoffHour ¶
CutoffHour returns the configured cutoff hour.
type Date ¶
type Date struct {
// contains filtered or unexported fields
}
Date represents a calendar date without clock or timezone information.
Date values use the year range supported by this library: MinDateYear through MaxDateYear.
func DateFromTime ¶
DateFromTime returns the calendar date part of t.
It uses the same validation rules as NewDate.
func MustDate ¶
MustDate returns a Date for the given calendar components.
It panics if the date is invalid. Intended for tests, constants, and example code.
func MustDateFromTime ¶
MustDateFromTime returns the calendar date part of t.
It panics if the date is invalid. Intended for tests, constants, and example code.
func MustParseDate ¶
MustParseDate parses input as a Date using auto-detected layout.
It panics if parsing fails. Intended for tests, constants, and example code.
func MustParseDateLayout ¶
func MustParseDateLayout(layout DateLayout, input string) Date
MustParseDateLayout parses input as a Date using layout.
It panics if parsing fails. Intended for tests, constants, and example code.
func NewDate ¶
NewDate returns a Date for the given calendar components.
The year must be in [MinDateYear, MaxDateYear]. Invalid dates such as February 31 return ErrInvalidDate. Go's time.Date normalizes overflow dates, so NewDate verifies that the resulting year, month, and day match the input.
func ParseDate ¶
ParseDate parses input as a Date using auto-detected layout.
It is equivalent to ParseDateLayout(DateLayoutAuto, input).
func ParseDateLayout ¶
func ParseDateLayout(layout DateLayout, input string) (Date, error)
ParseDateLayout parses input as a Date using layout.
Supported layouts are DateLayoutAuto, DateLayoutISO, and DateLayoutCompact. An empty input or unrecognized auto-detected format returns ErrParseDate. An unknown layout returns ErrInvalidLayout.
DateLayoutAuto chooses a layout from the input shape:
- length 10 with '-' at positions 4 and 7 -> DateLayoutISO (for example 2026-07-04)
- length 8 and all digits -> DateLayoutCompact (for example 20260704)
After parsing, the date is validated with NewDate. Parse and validation failures are returned as *ParseError values that support errors.Is for both ErrParseDate and the wrapped cause.
func (Date) AddDays ¶
AddDays returns the date that is days after d.
Negative days move backward. The calculation uses UTC calendar arithmetic. AddDays validates both d and the result. If either date is invalid or outside the supported year range, AddDays returns an error.
func (Date) After ¶
After reports whether d is later than other by calendar order.
After uses Compare and does not validate either Date.
func (Date) Before ¶
Before reports whether d is earlier than other by calendar order.
Before uses Compare and does not validate either Date.
func (Date) Compare ¶
Compare compares d and other by calendar order.
It returns -1 if d is before other, 1 if d is after other, and 0 if equal. Compare does not validate either Date; it compares the stored year, month, and day fields.
func (Date) Components ¶
Components returns the year, month, and day of d.
func (Date) Equal ¶
Equal reports whether d and other contain the same stored date fields.
Equal does not validate either Date.
func (Date) Format ¶
func (d Date) Format(layout DateLayout) (string, error)
Format returns a string representation of d using layout.
Supported layouts are DateLayoutAuto, DateLayoutISO, and DateLayoutCompact. DateLayoutAuto is treated as DateLayoutISO. An unknown layout returns ErrInvalidLayout.
func (Date) MarshalJSON ¶
MarshalJSON encodes d as a JSON string, for example "2026-07-04".
func (Date) MarshalText ¶
MarshalText validates d and encodes it as an ISO date string.
func (Date) MustAddDays ¶
MustAddDays returns the date that is days after d.
It panics if d is invalid or the result falls outside the supported year range. Intended for tests, constants, and example code.
func (Date) ToTime ¶
ToTime returns midnight on d in loc.
If loc is nil, time.Local is used. ToTime assumes d is valid; call Validate first if d may contain the zero value or another invalid date.
func (*Date) UnmarshalJSON ¶
UnmarshalJSON decodes d from a JSON string.
It delegates to UnmarshalText, so it accepts ISO and compact date strings and applies the same validation rules.
func (*Date) UnmarshalText ¶
UnmarshalText decodes d from an ISO or compact date string.
It delegates to ParseDate, so invalid calendar dates and unsupported shapes are rejected with parse errors that wrap the underlying validation cause.
func (Date) Valid ¶
Valid reports whether d represents a valid calendar date.
It is equivalent to d.Validate() == nil.
type DateLayout ¶
type DateLayout string
DateLayout selects the format used to parse and format Date values.
Supported layouts:
DateLayoutAuto -> auto-detect (2026-07-04 or 20260704) DateLayoutISO -> 2026-07-04 (default when formatting) DateLayoutCompact -> 20260704
const ( // DateLayoutAuto selects the date format automatically when parsing and // formats as DateLayoutISO. DateLayoutAuto DateLayout = "" // DateLayoutISO formats a date as YYYY-MM-DD, for example 2026-07-04. // This is the default date format. DateLayoutISO DateLayout = "YYYY-MM-DD" // DateLayoutCompact formats a date as YYYYMMDD, for example 20260704. DateLayoutCompact DateLayout = "YYYYMMDD" )
type DateTime ¶
type DateTime struct {
// contains filtered or unexported fields
}
DateTime represents a business date paired with an extended-hour clock.
DateTime has no timezone. Whether its clock is valid depends on the System used to construct or validate it. The default system allows clocks up to 30:00:00.
func FromTime ¶
FromTime converts a wall-clock time to a business DateTime using the default system.
With the default cutoff hour of 6, 2026-07-05 02:30 becomes 2026-07-04 26:30 and 2026-07-05 06:30 stays 2026-07-05 06:30. For custom systems, use System.FromTime.
func MustDateTime ¶
MustDateTime returns a DateTime with the given date and clock using the default system.
It panics if date or clock is invalid. Intended for tests, constants, and example code. For custom systems, use System.MustDateTime.
func MustParseDateTime ¶
MustParseDateTime parses input as a DateTime using the default system.
It panics if parsing fails. Intended for tests, constants, and example code. For custom systems, use System.MustParseDateTime.
func MustParseDateTimeLayout ¶
func MustParseDateTimeLayout(layout DateTimeLayout, input string) DateTime
MustParseDateTimeLayout parses input as a DateTime using the default system and layout.
It panics if parsing fails. Intended for tests, constants, and example code. For custom systems, use System.MustParseDateTimeLayout.
func NewDateTime ¶
NewDateTime returns a DateTime with the given date and clock using the default system.
The default system allows clocks up to 30:00:00. For custom systems, use System.NewDateTime.
func ParseDateTime ¶
ParseDateTime parses input as a DateTime using the default system and auto-detected layout.
It is equivalent to DefaultSystem().ParseDateTime(input). For custom systems, use System.ParseDateTime.
func ParseDateTimeLayout ¶
func ParseDateTimeLayout(layout DateTimeLayout, input string) (DateTime, error)
ParseDateTimeLayout parses input as a DateTime using the default system and layout.
It is equivalent to DefaultSystem().ParseDateTimeLayout(layout, input). For custom systems, use System.ParseDateTimeLayout.
func (DateTime) After ¶
After reports whether dt is later than other.
After does not validate either DateTime against a System.
func (DateTime) Before ¶
Before reports whether dt is earlier than other.
Before does not validate either DateTime against a System.
func (DateTime) Compare ¶
Compare performs a lexicographic comparison by stored business date and clock.
It returns -1 if dt is before other, 1 if dt is after other, and 0 if equal. Compare does not validate either DateTime against a System and does not normalize equivalent wall-clock instants such as 2026-07-04 30:00 and 2026-07-05 06:00. Use System.CompareDateTime for system-aware comparison.
func (DateTime) Components ¶
Components returns the date and clock parts of dt.
func (DateTime) Equal ¶
Equal reports whether dt and other represent the same date and clock values.
Equal does not validate either DateTime against a System.
func (DateTime) Format ¶
func (dt DateTime) Format(layout DateTimeLayout) (string, error)
Format returns a string representation of dt using layout.
Format does not validate dt against a System. DateTimeLayoutAuto is treated as DateTimeLayoutSpaceHMS. Space layouts join date and clock with a space; T layouts join with "T". The date is formatted as DateLayoutISO and the clock is formatted according to the layout precision. An unknown layout returns ErrInvalidLayout.
func (DateTime) Hour ¶
Hour returns the hour of the stored extended-hour clock.
The value may exceed 23, such as 26 for 26:30.
func (DateTime) MarshalJSON ¶
MarshalJSON encodes dt as a JSON string, for example "2026-07-04 26:30:00".
func (DateTime) MarshalText ¶
MarshalText encodes dt as text using String format.
MarshalText does not validate dt against a specific System.
func (DateTime) Nanosecond ¶
Nanosecond returns the nanosecond component of the stored clock.
func (DateTime) String ¶
String returns the default DateTime string, for example 2026-07-04 26:30:00.
func (DateTime) StringHM ¶
StringHM returns dt formatted to minute precision, for example 2026-07-04 26:30.
func (DateTime) StringHMS ¶
StringHMS returns dt formatted to second precision, for example 2026-07-04 26:30:00.
func (DateTime) StringNano ¶
StringNano returns dt formatted with a fixed 9-digit fractional second, for example 2026-07-04 26:30:00.120000000.
func (*DateTime) UnmarshalJSON ¶
UnmarshalJSON decodes dt from a JSON string.
It delegates to UnmarshalText, so it accepts the same library-supported DateTime range and does not perform system-specific validation.
func (*DateTime) UnmarshalText ¶
UnmarshalText decodes dt from text within the library-supported range.
Parsing uses the same lenient field rules as ParseDateTimeLayout. UnmarshalText does not validate dt against a specific System. Use System.ValidateDateTime after decoding when system-specific validation is required.
type DateTimeLayout ¶
type DateTimeLayout string
DateTimeLayout selects the format used to parse and format DateTime values.
Each layout combines an ISO date part and a clock part. Supported layouts:
DateTimeLayoutAuto -> auto-detect separator and clock precision DateTimeLayoutSpaceHM -> 2026-07-04 26:30 DateTimeLayoutSpaceHMS -> 2026-07-04 26:30:00 DateTimeLayoutSpaceNano -> 2026-07-04 26:30:00.123456789 DateTimeLayoutTHM -> 2026-07-04T26:30 DateTimeLayoutTHMS -> 2026-07-04T26:30:00 DateTimeLayoutTNano -> 2026-07-04T26:30:00.123456789
Timezone offsets are not supported, for example 2026-07-04T26:30:00+09:00.
const ( // DateTimeLayoutAuto selects the datetime format automatically when parsing // and formats as DateTimeLayoutSpaceHMS. DateTimeLayoutAuto DateTimeLayout = "" // DateTimeLayoutSpaceHM formats a datetime as "YYYY-MM-DD HH:MM", // for example 2026-07-04 26:30. DateTimeLayoutSpaceHM DateTimeLayout = "YYYY-MM-DD HH:MM" // DateTimeLayoutSpaceHMS formats a datetime as "YYYY-MM-DD HH:MM:SS", // for example 2026-07-04 26:30:00. DateTimeLayoutSpaceHMS DateTimeLayout = "YYYY-MM-DD HH:MM:SS" // DateTimeLayoutSpaceNano formats a datetime as // "YYYY-MM-DD HH:MM:SS.NNNNNNNNN", // for example 2026-07-04 26:30:00.123456789. DateTimeLayoutSpaceNano DateTimeLayout = "YYYY-MM-DD HH:MM:SS.NNNNNNNNN" // DateTimeLayoutTHM formats a datetime as "YYYY-MM-DDTHH:MM", // for example 2026-07-04T26:30. DateTimeLayoutTHM DateTimeLayout = "YYYY-MM-DDTHH:MM" // DateTimeLayoutTHMS formats a datetime as "YYYY-MM-DDTHH:MM:SS", // for example 2026-07-04T26:30:00. DateTimeLayoutTHMS DateTimeLayout = "YYYY-MM-DDTHH:MM:SS" // DateTimeLayoutTNano formats a datetime as // "YYYY-MM-DDTHH:MM:SS.NNNNNNNNN", // for example 2026-07-04T26:30:00.123456789. DateTimeLayoutTNano DateTimeLayout = "YYYY-MM-DDTHH:MM:SS.NNNNNNNNN" )
type ParseError ¶
type ParseError struct {
// Layout is the layout requested by the caller, or empty for auto layout.
Layout string
// Input is the original input string after outer whitespace trimming.
Input string
// Err is the underlying parse or validation cause.
Err error
// contains filtered or unexported fields
}
ParseError reports a failure to parse input with a specific layout.
ParseError unwraps the underlying cause and also matches the parse category with errors.Is, such as ErrParseClock, ErrParseDate, or ErrParseDateTime.
func (*ParseError) Error ¶
func (e *ParseError) Error() string
Error returns the formatted parse error message.
func (*ParseError) Is ¶
func (e *ParseError) Is(target error) bool
Is reports whether target is the parse category for e.
The wrapped cause remains available through Unwrap, so errors.Is can match both the parse category and the underlying validation error.
func (*ParseError) Unwrap ¶
func (e *ParseError) Unwrap() error
Unwrap returns the underlying parse or validation cause.
type System ¶
type System struct {
// contains filtered or unexported fields
}
System owns cutoff-hour-specific rules for clocks and business dates.
Use System methods when a value must be constructed, formatted, converted, compared, or validated under a custom system instead of the default system.
func DefaultSystem ¶
func DefaultSystem() System
DefaultSystem returns a System that uses the default 30-hour clock rules.
The returned system has cutoff hour 6 and maximum clock hour 30:
DefaultSystem().CutoffHour() == 6 DefaultSystem().MaxHour() == 30
func MustSystem ¶
MustSystem returns a System backed by the given configuration.
It panics if config is invalid. This function is intended for tests, package-level variable initialization, and example code where a valid configuration is known at compile time or setup time.
func NewSystem ¶
NewSystem returns a System for the given configuration.
Config values are typically obtained from DefaultConfig, NewConfig, MustConfig, or Config{} (cutoff hour 0). If config is invalid, NewSystem returns a zero System and the validation error.
func (System) AddClockDurationBounded ¶
AddClockDurationBounded adds d to c without wrapping across a business day.
c must be valid under the system. The sum is computed from Clock 00:00; if the result is negative or exceeds MaxHour():00:00, AddClockDurationBounded returns ErrOutOfRange. There is no wrap-around.
For example, with the default system (max 30:00:00):
29:30 + 30m -> 30:00 29:30 + 1h -> error
Use ShiftClockDuration when the result should wrap to an adjacent business day.
func (System) AddDateTime ¶
AddDateTime adds d to dt in business date and extended-hour clock space.
It is equivalent to AddDateTimeDuration. The result preserves extended-hour representation and may cross to an adjacent business day.
func (System) AddDateTimeDuration ¶
AddDateTimeDuration adds d to dt in business date and extended-hour clock space.
The result may cross to an adjacent business day. For example, with the default system:
2026-07-04 29:30 + 1h -> 2026-07-05 06:30 2026-07-04 30:00 + 1ns -> 2026-07-05 06:00:00.000000001 2026-07-04 00:30 - 1h -> 2026-07-03 23:30
Use AddDateTimeDurationBounded when the result must stay on the same business day.
func (System) AddDateTimeDurationBounded ¶
AddDateTimeDurationBounded adds d to dt without shifting to another business day.
If the result would move to an adjacent business day, it returns ErrOutOfRange. For example, with the default system:
2026-07-04 29:30 + 30m -> 2026-07-04 30:00 2026-07-04 29:30 + 1h -> error
func (System) AfterClock ¶
AfterClock reports whether a is later than b after validating both under the system.
func (System) AfterDateTime ¶
AfterDateTime reports whether a is after b as a normalized wall-clock instant.
It uses CompareDateTime, so it performs system-aware comparison rather than lexicographic comparison of stored DateTime fields.
func (System) BeforeClock ¶
BeforeClock reports whether a is earlier than b after validating both under the system.
func (System) BeforeDateTime ¶
BeforeDateTime reports whether a is before b as a normalized wall-clock instant.
It uses CompareDateTime, so it performs system-aware comparison rather than lexicographic comparison of stored DateTime fields.
func (System) ClockFromDuration ¶
ClockFromDuration converts a duration to a Clock validated by the system.
Negative durations and values greater than MaxHour():00:00 return ErrOutOfRange. The maximum duration MaxHour() hours is valid.
func (System) CompareClock ¶
CompareClock compares a and b after validating both under the system.
It returns -1 if a is before b, 1 if a is after b, and 0 if equal.
func (System) CompareDateTime ¶
CompareDateTime performs a system-aware comparison of a and b.
It validates both values and compares normalized wall-clock instants. Equivalent wall-clock instants such as 2026-07-04 30:00 and 2026-07-05 06:00 compare as equal under the default system. It returns -1 if a is before b, 1 if a is after b, and 0 if equal. If normalization would move outside the supported Date range, it returns an error wrapping ErrInvalidDateTime and ErrInvalidDate.
func (System) CutoffHour ¶
CutoffHour returns the cutoff hour configured for the system.
Local times from 00:00 up to, but not including, cutoffHour belong to the previous business day. For example, when cutoffHour is 6, 02:30 is represented as 26:30 on the previous business date.
func (System) DayRange ¶
func (s System) DayRange(year int, month time.Month, day int, loc *time.Location) (start, end time.Time, err error)
DayRange returns the half-open wall-clock time range for a business date.
It is equivalent to creating the date with NewDate and calling DayRangeDate.
func (System) DayRangeDate ¶
DayRangeDate returns the half-open wall-clock time range for a business date.
The range starts at CutoffHour on the calendar date and ends one calendar day later: [start, end). If loc is nil, time.Local is used.
func (System) EqualClock ¶
EqualClock reports whether a and b are equal after validating both under the system.
func (System) EqualDateTime ¶
EqualDateTime reports whether a and b are the same normalized wall-clock instant.
It uses CompareDateTime, so it performs system-aware comparison rather than comparing the stored business date and clock fields as DateTime.Equal does.
func (System) FormatClock ¶
func (s System) FormatClock(c Clock, layout ClockLayout) (string, error)
FormatClock validates c under the system and formats it with layout.
Unlike Clock.Format, FormatClock checks that c is valid under the system before formatting.
func (System) FormatDateTime ¶
func (s System) FormatDateTime(dt DateTime, layout DateTimeLayout) (string, error)
FormatDateTime validates dt under the system and formats it with layout.
Unlike DateTime.Format, FormatDateTime checks that dt is valid under the system before formatting.
func (System) FromTime ¶
FromTime converts a wall-clock time to a business DateTime under the system.
The natural calendar date and clock are taken from t in t's location. If the hour is before CutoffHour, the business date is the previous calendar day and the business hour is increased by 24.
func (System) IsMaxClock ¶
IsMaxClock reports whether c is the maximum clock value allowed by the system.
The maximum clock is MaxHour():00:00.000000000. For example:
cutoffHour = 0 -> 24:00:00 is max cutoffHour = 6 -> 30:00:00 is max cutoffHour = 10 -> 34:00:00 is max
IsMaxClock compares stored fields only and does not validate c.
func (System) MaxHour ¶
MaxHour returns the highest hour value allowed by the system.
It equals 24 plus the cutoff hour. Examples:
cutoffHour = 0 -> maxHour = 24 cutoffHour = 6 -> maxHour = 30 cutoffHour = 10 -> maxHour = 34
func (System) MustClock ¶
MustClock returns a Clock with the given components, validated by the system.
It panics if the components are invalid. Intended for tests, constants, and example code.
func (System) MustDateTime ¶
MustDateTime returns a DateTime with the given date and clock, validated by the system.
It panics if date or clock is invalid. Intended for tests, constants, and example code.
func (System) MustParseClock ¶
MustParseClock parses input as a Clock using auto-detected layout.
It panics if parsing fails. Intended for tests, constants, and example code.
func (System) MustParseClockLayout ¶
func (s System) MustParseClockLayout(layout ClockLayout, input string) Clock
MustParseClockLayout parses input as a Clock using layout.
It panics if parsing fails. Intended for tests, constants, and example code.
func (System) MustParseDateTime ¶
MustParseDateTime parses input as a DateTime using auto-detected layout.
It panics if parsing fails. Intended for tests, constants, and example code.
func (System) MustParseDateTimeLayout ¶
func (s System) MustParseDateTimeLayout(layout DateTimeLayout, input string) DateTime
MustParseDateTimeLayout parses input as a DateTime using layout.
It panics if parsing fails. Intended for tests, constants, and example code.
func (System) NewClock ¶
NewClock returns a Clock with the given components, validated by the system.
On success it returns the constructed Clock. On failure it returns a zero Clock and an error from ValidateClock.
func (System) NewClockHM ¶
NewClockHM returns a Clock with hour and minute precision (HH:MM).
Second and nanosecond are set to zero. See NewClock for validation rules.
func (System) NewClockHMS ¶
NewClockHMS returns a Clock with hour, minute, and second precision (HH:MM:SS).
Nanosecond is set to zero. See NewClock for validation rules.
func (System) NewDateTime ¶
NewDateTime returns a DateTime with the given date and clock, validated by the system.
On success it returns the constructed DateTime. On failure it returns a zero DateTime and an error wrapping ErrInvalidDateTime. The wrapped error still supports errors.Is for ErrInvalidDate or ErrInvalidClock.
func (System) ParseClock ¶
ParseClock parses input as a Clock using auto-detected layout.
It is equivalent to ParseClockLayout(ClockLayoutAuto, input) on the same system.
func (System) ParseClockLayout ¶
func (s System) ParseClockLayout(layout ClockLayout, input string) (Clock, error)
ParseClockLayout parses input as a Clock using layout.
Supported layouts are ClockLayoutAuto, ClockLayoutHM, ClockLayoutHMS, and ClockLayoutNano. An empty input or unrecognized auto-detected format returns ErrParseClock. An unknown layout returns ErrInvalidLayout.
Parsing is lenient. Each field is a decimal integer and leading zeros are not required. For example, ClockLayoutHM accepts "6:30" and "26:5" as well as "06:30". ClockLayoutHMS accepts "26:30:0". ClockLayoutNano accepts fractional seconds with 1 to 9 digits. The input must still match the layout structure: the correct number of colon-separated fields, and a dot before the fractional second in ClockLayoutNano.
ClockLayoutAuto chooses a layout from the input shape:
- contains "." -> ClockLayoutNano
- one ":" -> ClockLayoutHM
- two ":" -> ClockLayoutHMS
After parsing, the clock is validated under the system. Parse and validation failures are returned as *ParseError values that support errors.Is for both ErrParseClock and the wrapped cause.
func (System) ParseDateTime ¶
ParseDateTime parses input as a DateTime using auto-detected layout.
It is equivalent to ParseDateTimeLayout(DateTimeLayoutAuto, input) on the same system.
func (System) ParseDateTimeLayout ¶
func (s System) ParseDateTimeLayout(layout DateTimeLayout, input string) (DateTime, error)
ParseDateTimeLayout parses input as a DateTime using layout.
Supported layouts are DateTimeLayoutAuto and the Space/T variants with HM, HMS, or Nano clock precision. An empty input or unrecognized auto-detected format returns ErrParseDateTime. An unknown layout returns ErrInvalidLayout.
DateTimeLayoutAuto chooses a layout from the input shape:
- contains "T" -> T series; otherwise contains " " -> Space series
- clock contains "." -> Nano
- clock has one ":" -> HM
- clock has two ":" -> HMS
The date part is parsed as DateLayoutISO. The clock part is parsed under the system. After parsing, the DateTime is validated with NewDateTime. Parse and validation failures are returned as *ParseError values that support errors.Is for both ErrParseDateTime and the wrapped cause.
func (System) ShiftClockDuration ¶
func (s System) ShiftClockDuration(c Clock, d time.Duration) (clock Clock, dayOffset int, err error)
ShiftClockDuration adds d to c and may shift across business days.
c must be valid under the system. The sum is computed from Clock 00:00, not from the real business-day boundary. When the result falls outside the representable range [00:00:00, MaxHour():00:00], it wraps into an adjacent business day by adding or subtracting 24 hours per day crossed.
dayOffset is 0 when the result stays on the same business day, positive when it advances to a later day, and negative when it moves to an earlier day.
For example, with the default system (max 30:00:00):
29:30 + 30m -> 30:00, dayOffset 0 29:30 + 1h -> 06:30, dayOffset 1 30:00 + 0 -> 30:00, dayOffset 0 30:00 + 1ns -> 06:00:00.000000001, dayOffset 1
func (System) SubClock ¶
SubClock returns the duration from b to a (a - b).
The result is a time.Duration and may be positive, zero, or negative. It does not wrap or return a Clock.
For example:
27:00 - 26:30 = 30m 26:30 - 27:00 = -30m
Both clocks must be valid under the system.
func (System) SubClockDurationBounded ¶
SubClockDurationBounded subtracts d from c without wrapping across a business day.
c must be valid under the system. The difference is computed from Clock 00:00; if the result is negative or exceeds MaxHour():00:00, SubClockDurationBounded returns ErrOutOfRange. There is no wrap-around.
For example, with the default system (max 30:00:00):
00:30 - 1h -> error
Use UnshiftClockDuration when the result should wrap to an adjacent business day.
func (System) SubDateTime ¶
SubDateTime returns the elapsed business time from b to a (a - b).
The result is computed from stored business date fields plus extended-hour clock fields; it does not convert values with ToTime. This matches normalized wall-clock equivalence for adjacent extended-hour representations: 2026-07-04 30:00 and 2026-07-05 06:00 differ by zero. If the difference cannot be represented as a time.Duration, SubDateTime returns ErrOutOfRange.
func (System) SubDateTimeDuration ¶
SubDateTimeDuration subtracts d from dt in business date and extended-hour clock space.
The result may cross to an adjacent business day. Use SubDateTimeDurationBounded when the result must stay on the same business day.
func (System) SubDateTimeDurationBounded ¶
SubDateTimeDurationBounded subtracts d from dt without shifting to another business day.
If the result would move to an adjacent business day, it returns ErrOutOfRange. For example, with the default system:
2026-07-04 00:30 - 1h -> error
func (System) ToTime ¶
ToTime converts a business DateTime to a wall-clock time in loc.
If loc is nil, time.Local is used. When the business hour is 24 or greater, the real calendar date is the next day and the real hour is reduced by 24. If that normalization would move outside the supported Date range, ToTime returns an error wrapping ErrInvalidDateTime and ErrInvalidDate.
func (System) UnshiftClockDuration ¶
func (s System) UnshiftClockDuration(c Clock, d time.Duration) (clock Clock, dayOffset int, err error)
UnshiftClockDuration subtracts d from c and may shift across business days.
c must be valid under the system. When the result falls outside the representable range, it wraps into an adjacent business day by adding or subtracting 24 hours per day crossed.
For example, with the default system (max 30:00:00):
00:30 - 1h -> 23:30, dayOffset -1
func (System) ValidClock ¶
ValidClock reports whether c is a valid clock value under the system.
It is equivalent to s.ValidateClock(c) == nil.
func (System) ValidDateTime ¶
ValidDateTime reports whether dt is valid under the system.
It is equivalent to s.ValidateDateTime(dt) == nil.
func (System) ValidateClock ¶
ValidateClock reports whether c is a valid clock value under the system.
A valid clock satisfies:
- 0 <= hour <= MaxHour()
- 0 <= minute, second <= 59
- 0 <= nanosecond <= 999_999_999
- when hour equals MaxHour(), minute, second, and nanosecond are 0
For example, when MaxHour() is 30, 30:00:00 is valid but 30:00:01 is not.
Returns nil if c is valid. Otherwise returns ErrInvalidConfig, ErrOutOfRange, or ErrInvalidClock.
func (System) ValidateDateTime ¶
ValidateDateTime reports whether dt is valid under the system.
It validates the date and clock components. On failure it returns an error wrapping ErrInvalidDateTime. The wrapped error still supports errors.Is for ErrInvalidDate or ErrInvalidClock. A DateTime can be valid here but still fail system-aware normalization, such as converting an extended-hour value on MaxDateYear-12-31 to wall-clock time.