265 lines
11 KiB
Go
265 lines
11 KiB
Go
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()
|
|
}
|