package timefmt // Fragment represents a single component of a time format. // It maps between Go's reference time format, LDML tokens, and human-readable descriptions. type Fragment struct { // GoFormat is Go's reference time format (e.g., "2006" for 4-digit year) GoFormat string // LDML is the Unicode LDML token (e.g., "yyyy" for 4-digit year) LDML string // Description is a human-readable English description (e.g., "Year (4-digit)") Description string } // Year fragments represent different year formats var ( // Year4Digit represents a 4-digit year (e.g., 2026) Year4Digit = Fragment{GoFormat: "2006", LDML: "yyyy", Description: "Year (4-digit)"} // Year2Digit represents a 2-digit year (e.g., 26) Year2Digit = Fragment{GoFormat: "06", LDML: "yy", Description: "Year (2-digit)"} ) // Month fragments represent different month formats var ( // MonthNumeric represents a numeric month without leading zero (1-12) MonthNumeric = Fragment{GoFormat: "1", LDML: "M", Description: "Month (numeric)"} // MonthNumeric2 represents a 2-digit month with leading zero (01-12) MonthNumeric2 = Fragment{GoFormat: "01", LDML: "MM", Description: "Month (2-digit)"} // MonthShort represents an abbreviated month name (Jan, Feb, Mar, etc.) MonthShort = Fragment{GoFormat: "Jan", LDML: "MMM", Description: "Month (abbreviated)"} // MonthFull represents a full month name (January, February, March, etc.) MonthFull = Fragment{GoFormat: "January", LDML: "MMMM", Description: "Month (full name)"} ) // Day fragments represent different day-of-month formats var ( // DayNumeric represents a numeric day without leading zero (1-31) DayNumeric = Fragment{GoFormat: "2", LDML: "d", Description: "Day (numeric)"} // DayNumeric2 represents a 2-digit day with leading zero (01-31) DayNumeric2 = Fragment{GoFormat: "02", LDML: "dd", Description: "Day (2-digit)"} // DaySpacePadded represents a space-padded day ( 1-31) DaySpacePadded = Fragment{GoFormat: "_2", LDML: "d", Description: "Day (space-padded)"} // DayOfYearNumeric represents the day of year as a 3-digit number (001-365) DayOfYearNumeric = Fragment{GoFormat: "002", LDML: "DDD", Description: "Day of year (3-digit)"} // DayOfYearSpacePadded represents the day of year as a space-padded number ( 1-365) DayOfYearSpacePadded = Fragment{GoFormat: "__2", LDML: "DDD", Description: "Day of year (space-padded)"} ) // Weekday fragments represent different weekday formats var ( // WeekdayShort represents an abbreviated weekday name (Mon, Tue, Wed, etc.) WeekdayShort = Fragment{GoFormat: "Mon", LDML: "EEE", Description: "Weekday (abbreviated)"} // WeekdayFull represents a full weekday name (Monday, Tuesday, Wednesday, etc.) WeekdayFull = Fragment{GoFormat: "Monday", LDML: "EEEE", Description: "Weekday (full name)"} ) // Hour fragments represent different hour formats var ( // Hour24 represents 24-hour format with leading zero (00-23) Hour24 = Fragment{GoFormat: "15", LDML: "HH", Description: "Hour (24-hour, 2-digit)"} // Hour12 represents 12-hour format without leading zero (1-12) Hour12 = Fragment{GoFormat: "3", LDML: "h", Description: "Hour (12-hour)"} // Hour12Padded represents 12-hour format with leading zero (01-12) Hour12Padded = Fragment{GoFormat: "03", LDML: "hh", Description: "Hour (12-hour, 2-digit)"} ) // Minute fragments represent different minute formats var ( // Minute represents minutes with leading zero (00-59) Minute = Fragment{GoFormat: "04", LDML: "mm", Description: "Minute (2-digit)"} // MinuteUnpadded represents minutes without leading zero (0-59) MinuteUnpadded = Fragment{GoFormat: "4", LDML: "m", Description: "Minute"} ) // Second fragments represent different second formats var ( // Second represents seconds with leading zero (00-59) Second = Fragment{GoFormat: "05", LDML: "ss", Description: "Second (2-digit)"} // SecondUnpadded represents seconds without leading zero (0-59) SecondUnpadded = Fragment{GoFormat: "5", LDML: "s", Description: "Second"} ) // Subsecond fragments represent fractional seconds var ( // Millisecond represents milliseconds as 3 digits (.000) Millisecond = Fragment{GoFormat: ".000", LDML: ".SSS", Description: "Millisecond (3-digit)"} // MillisecondTrim represents milliseconds with trailing zeros removed (.999) MillisecondTrim = Fragment{GoFormat: ".999", LDML: ".SSS", Description: "Millisecond (trim zeros)"} // Microsecond represents microseconds as 6 digits (.000000) Microsecond = Fragment{GoFormat: ".000000", LDML: ".SSSSSS", Description: "Microsecond (6-digit)"} // MicrosecondTrim represents microseconds with trailing zeros removed (.999999) MicrosecondTrim = Fragment{GoFormat: ".999999", LDML: ".SSSSSS", Description: "Microsecond (trim zeros)"} // Nanosecond represents nanoseconds as 9 digits (.000000000) Nanosecond = Fragment{GoFormat: ".000000000", LDML: ".SSSSSSSSS", Description: "Nanosecond (9-digit)"} // NanosecondTrim represents nanoseconds with trailing zeros removed (.999999999) NanosecondTrim = Fragment{GoFormat: ".999999999", LDML: ".SSSSSSSSS", Description: "Nanosecond (trim zeros)"} ) // AMPM fragments represent AM/PM markers var ( // AMPM represents AM/PM in uppercase AMPM = Fragment{GoFormat: "PM", LDML: "a", Description: "AM/PM (uppercase)"} // AMPMLower represents am/pm in lowercase AMPMLower = Fragment{GoFormat: "pm", LDML: "a", Description: "AM/PM (lowercase)"} ) // Timezone fragments represent different timezone formats var ( // TimezoneOffset represents timezone offset as ±HHMM (e.g., -0700) TimezoneOffset = Fragment{GoFormat: "-0700", LDML: "ZZZ", Description: "Timezone offset (±HHMM)"} // TimezoneOffsetColon represents timezone offset as ±HH:MM (e.g., -07:00) TimezoneOffsetColon = Fragment{GoFormat: "-07:00", LDML: "ZZZZZ", Description: "Timezone offset (±HH:MM)"} // TimezoneOffsetHourOnly represents timezone offset hours only as ±HH (e.g., -07) TimezoneOffsetHourOnly = Fragment{GoFormat: "-07", LDML: "ZZ", Description: "Timezone offset (±HH)"} // TimezoneOffsetSeconds represents timezone offset with seconds as ±HHMMSS (e.g., -070000) TimezoneOffsetSeconds = Fragment{GoFormat: "-070000", LDML: "ZZZZ", Description: "Timezone offset (±HHMMSS)"} // TimezoneOffsetColonSeconds represents timezone offset with seconds as ±HH:MM:SS (e.g., -07:00:00) TimezoneOffsetColonSeconds = Fragment{GoFormat: "-07:00:00", LDML: "ZZZZZ", Description: "Timezone offset (±HH:MM:SS)"} // TimezoneISO8601 represents ISO 8601 timezone with Z for UTC (e.g., Z or -0700) TimezoneISO8601 = Fragment{GoFormat: "Z0700", LDML: "ZZZ", Description: "ISO 8601 timezone (Z or ±HHMM)"} // TimezoneISO8601Colon represents ISO 8601 timezone with colon (e.g., Z or -07:00) TimezoneISO8601Colon = Fragment{GoFormat: "Z07:00", LDML: "ZZZZZ", Description: "ISO 8601 timezone (Z or ±HH:MM)"} // TimezoneName represents timezone abbreviation (e.g., MST, PST) TimezoneName = Fragment{GoFormat: "MST", LDML: "zzz", Description: "Timezone abbreviation"} ) // Pre-built common formats for convenience. // These are initialized in init() to avoid initialization cycles. var ( // ISO8601 represents the ISO 8601 datetime format: 2006-01-02T15:04:05Z07:00 ISO8601 *Format // RFC3339 represents the RFC 3339 datetime format (same as ISO8601): 2006-01-02T15:04:05Z07:00 RFC3339 *Format // RFC3339Nano represents the RFC 3339 datetime format with nanoseconds: 2006-01-02T15:04:05.999999999Z07:00 RFC3339Nano *Format // DateOnly represents a date-only format: 2006-01-02 DateOnly *Format // TimeOnly represents a time-only format: 15:04:05 TimeOnly *Format // DateTime represents a simple datetime format: 2006-01-02 15:04:05 DateTime *Format // DateTimeWithMillis represents datetime with milliseconds: 2006-01-02 15:04:05.000 DateTimeWithMillis *Format // DateUS represents US date format: 01/02/2006 DateUS *Format // DateEU represents European date format: 02/01/2006 DateEU *Format // DateTimeUS represents US datetime format: 01/02/2006 3:04:05 PM DateTimeUS *Format // DateTimeEU represents European datetime format: 02/01/2006 15:04:05 DateTimeEU *Format // Kitchen represents kitchen time format: 3:04 PM Kitchen *Format // Stamp represents a timestamp format: Jan _2 15:04:05 Stamp *Format // StampMilli represents a timestamp with milliseconds: Jan _2 15:04:05.000 StampMilli *Format // StampMicro represents a timestamp with microseconds: Jan _2 15:04:05.000000 StampMicro *Format // StampNano represents a timestamp with nanoseconds: Jan _2 15:04:05.000000000 StampNano *Format ) func init() { // ISO 8601 / RFC 3339: 2006-01-02T15:04:05Z07:00 ISO8601 = NewBuilder(). Year4().Dash().MonthNumeric2().Dash().DayNumeric2(). T(). Hour24().Colon().Minute().Colon().Second(). TimezoneISO8601Colon(). Build() RFC3339 = ISO8601 // RFC 3339 is the same as ISO 8601 // RFC 3339 with nanoseconds: 2006-01-02T15:04:05.999999999Z07:00 RFC3339Nano = NewBuilder(). Year4().Dash().MonthNumeric2().Dash().DayNumeric2(). T(). Hour24().Colon().Minute().Colon().Second(). NanosecondTrim(). TimezoneISO8601Colon(). Build() // Date only: 2006-01-02 DateOnly = NewBuilder(). Year4().Dash().MonthNumeric2().Dash().DayNumeric2(). Build() // Time only: 15:04:05 TimeOnly = NewBuilder(). Hour24().Colon().Minute().Colon().Second(). Build() // DateTime: 2006-01-02 15:04:05 DateTime = NewBuilder(). Year4().Dash().MonthNumeric2().Dash().DayNumeric2(). Space(). Hour24().Colon().Minute().Colon().Second(). Build() // DateTime with milliseconds: 2006-01-02 15:04:05.000 DateTimeWithMillis = NewBuilder(). Year4().Dash().MonthNumeric2().Dash().DayNumeric2(). Space(). Hour24().Colon().Minute().Colon().Second(). Millisecond(). Build() // US date: 01/02/2006 DateUS = NewBuilder(). MonthNumeric2().Slash().DayNumeric2().Slash().Year4(). Build() // European date: 02/01/2006 DateEU = NewBuilder(). DayNumeric2().Slash().MonthNumeric2().Slash().Year4(). Build() // US datetime: 01/02/2006 3:04:05 PM DateTimeUS = NewBuilder(). MonthNumeric2().Slash().DayNumeric2().Slash().Year4(). Space(). Hour12().Colon().Minute().Colon().Second(). Space().AMPM(). Build() // European datetime: 02/01/2006 15:04:05 DateTimeEU = NewBuilder(). DayNumeric2().Slash().MonthNumeric2().Slash().Year4(). Space(). Hour24().Colon().Minute().Colon().Second(). Build() // Kitchen: 3:04 PM Kitchen = NewBuilder(). Hour12().Colon().Minute(). Space().AMPM(). Build() // Stamp: Jan _2 15:04:05 Stamp = NewBuilder(). MonthShort().Space().DaySpacePadded().Space(). Hour24().Colon().Minute().Colon().Second(). Build() // Stamp with milliseconds: Jan _2 15:04:05.000 StampMilli = NewBuilder(). MonthShort().Space().DaySpacePadded().Space(). Hour24().Colon().Minute().Colon().Second(). Millisecond(). Build() // Stamp with microseconds: Jan _2 15:04:05.000000 StampMicro = NewBuilder(). MonthShort().Space().DaySpacePadded().Space(). Hour24().Colon().Minute().Colon().Second(). Microsecond(). Build() // Stamp with nanoseconds: Jan _2 15:04:05.000000000 StampNano = NewBuilder(). MonthShort().Space().DaySpacePadded().Space(). Hour24().Colon().Minute().Colon().Second(). Nanosecond(). Build() }