Files
timefmt/builder_test.go
2026-02-08 16:10:41 +11:00

347 lines
7.2 KiB
Go

package timefmt
import (
"testing"
"time"
)
func TestBuilder_BasicFormats(t *testing.T) {
tests := []struct {
name string
builder func() *Builder
wantGo string
wantLDML string
}{
{
name: "ISO 8601 date",
builder: func() *Builder {
return NewBuilder().
Year4().Dash().MonthNumeric2().Dash().DayNumeric2()
},
wantGo: "2006-01-02",
wantLDML: "yyyy-MM-dd",
},
{
name: "24-hour time",
builder: func() *Builder {
return NewBuilder().
Hour24().Colon().Minute().Colon().Second()
},
wantGo: "15:04:05",
wantLDML: "HH:mm:ss",
},
{
name: "Full datetime",
builder: func() *Builder {
return NewBuilder().
Year4().Dash().MonthNumeric2().Dash().DayNumeric2().
Space().
Hour24().Colon().Minute().Colon().Second()
},
wantGo: "2006-01-02 15:04:05",
wantLDML: "yyyy-MM-dd HH:mm:ss",
},
{
name: "12-hour with AM/PM",
builder: func() *Builder {
return NewBuilder().
Hour12().Colon().Minute().Space().AMPM()
},
wantGo: "3:04 PM",
wantLDML: "h:mm a",
},
{
name: "US date format",
builder: func() *Builder {
return NewBuilder().
MonthNumeric2().Slash().DayNumeric2().Slash().Year4()
},
wantGo: "01/02/2006",
wantLDML: "MM/dd/yyyy",
},
{
name: "European date format",
builder: func() *Builder {
return NewBuilder().
DayNumeric2().Slash().MonthNumeric2().Slash().Year4()
},
wantGo: "02/01/2006",
wantLDML: "dd/MM/yyyy",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
format := tt.builder().Build()
gotGo := format.GoFormat()
if gotGo != tt.wantGo {
t.Errorf("GoFormat() = %q, want %q", gotGo, tt.wantGo)
}
gotLDML := format.LDML()
if gotLDML != tt.wantLDML {
t.Errorf("LDML() = %q, want %q", gotLDML, tt.wantLDML)
}
})
}
}
func TestBuilder_ChainableMethods(t *testing.T) {
// Test that all methods return *Builder for chaining
builder := NewBuilder()
result := builder.
Year4().Year2().
MonthNumeric().MonthNumeric2().MonthShort().MonthFull().
DayNumeric().DayNumeric2().DaySpacePadded().DayOfYear().
WeekdayShort().WeekdayFull().
Hour24().Hour12().Hour12Padded().
Minute().MinuteUnpadded().
Second().SecondUnpadded().
Millisecond().Microsecond().Nanosecond().
AMPM().AMPMLower().
TimezoneOffset().TimezoneOffsetColon().TimezoneName().
Literal("test").Dash().Slash().Colon().Space().T().Comma().Period()
if result == nil {
t.Error("Builder methods should return *Builder for chaining")
}
// Verify it's the same builder instance (mutable pattern)
if result != builder {
t.Error("Builder methods should return the same builder instance")
}
}
func TestBuilder_LiteralShortcuts(t *testing.T) {
tests := []struct {
name string
builder func() *Builder
want string
}{
{
name: "Dash",
builder: func() *Builder { return NewBuilder().Dash() },
want: "-",
},
{
name: "Slash",
builder: func() *Builder { return NewBuilder().Slash() },
want: "/",
},
{
name: "Colon",
builder: func() *Builder { return NewBuilder().Colon() },
want: ":",
},
{
name: "Space",
builder: func() *Builder { return NewBuilder().Space() },
want: " ",
},
{
name: "T",
builder: func() *Builder { return NewBuilder().T() },
want: "T",
},
{
name: "Comma",
builder: func() *Builder { return NewBuilder().Comma() },
want: ", ",
},
{
name: "Period",
builder: func() *Builder { return NewBuilder().Period() },
want: ".",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
format := tt.builder().Build()
got := format.GoFormat()
if got != tt.want {
t.Errorf("GoFormat() = %q, want %q", got, tt.want)
}
})
}
}
func TestBuilder_ComplexFormat(t *testing.T) {
// Build a complex format with multiple components
format := NewBuilder().
WeekdayFull().Comma().
MonthFull().Space().DayNumeric().Comma().Year4().
Space().Literal("at").Space().
Hour12().Colon().Minute().Space().AMPM().
Space().Literal("(").TimezoneName().Literal(")").
Build()
wantGo := "Monday, January 2, 2006 at 3:04 PM (MST)"
gotGo := format.GoFormat()
if gotGo != wantGo {
t.Errorf("GoFormat() = %q, want %q", gotGo, wantGo)
}
// Test that it actually formats correctly
testTime := time.Date(2026, time.February, 8, 15, 4, 5, 0, time.FixedZone("MST", -7*3600))
formatted := format.Format(testTime)
expected := "Sunday, February 8, 2026 at 3:04 PM (MST)"
if formatted != expected {
t.Errorf("Format() = %q, want %q", formatted, expected)
}
}
func TestPrebuiltFormats(t *testing.T) {
tests := []struct {
name string
format *Format
wantGo string
}{
{
name: "ISO8601",
format: ISO8601,
wantGo: "2006-01-02T15:04:05Z07:00",
},
{
name: "RFC3339",
format: RFC3339,
wantGo: "2006-01-02T15:04:05Z07:00",
},
{
name: "RFC3339Nano",
format: RFC3339Nano,
wantGo: "2006-01-02T15:04:05.999999999Z07:00",
},
{
name: "DateOnly",
format: DateOnly,
wantGo: "2006-01-02",
},
{
name: "TimeOnly",
format: TimeOnly,
wantGo: "15:04:05",
},
{
name: "DateTime",
format: DateTime,
wantGo: "2006-01-02 15:04:05",
},
{
name: "DateTimeWithMillis",
format: DateTimeWithMillis,
wantGo: "2006-01-02 15:04:05.000",
},
{
name: "DateUS",
format: DateUS,
wantGo: "01/02/2006",
},
{
name: "DateEU",
format: DateEU,
wantGo: "02/01/2006",
},
{
name: "DateTimeUS",
format: DateTimeUS,
wantGo: "01/02/2006 3:04:05 PM",
},
{
name: "DateTimeEU",
format: DateTimeEU,
wantGo: "02/01/2006 15:04:05",
},
{
name: "Kitchen",
format: Kitchen,
wantGo: "3:04 PM",
},
{
name: "Stamp",
format: Stamp,
wantGo: "Jan _2 15:04:05",
},
{
name: "StampMilli",
format: StampMilli,
wantGo: "Jan _2 15:04:05.000",
},
{
name: "StampMicro",
format: StampMicro,
wantGo: "Jan _2 15:04:05.000000",
},
{
name: "StampNano",
format: StampNano,
wantGo: "Jan _2 15:04:05.000000000",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.format == nil {
t.Fatal("Format is nil")
}
gotGo := tt.format.GoFormat()
if gotGo != tt.wantGo {
t.Errorf("GoFormat() = %q, want %q", gotGo, tt.wantGo)
}
// Verify LDML and Description don't panic
_ = tt.format.LDML()
_ = tt.format.Description()
_ = tt.format.Example()
})
}
}
func TestPrebuiltFormats_Formatting(t *testing.T) {
testTime := time.Date(2026, time.February, 8, 15, 4, 5, 123456789, time.UTC)
tests := []struct {
name string
format *Format
want string
}{
{
name: "DateOnly",
format: DateOnly,
want: "2026-02-08",
},
{
name: "TimeOnly",
format: TimeOnly,
want: "15:04:05",
},
{
name: "DateTime",
format: DateTime,
want: "2026-02-08 15:04:05",
},
{
name: "DateUS",
format: DateUS,
want: "02/08/2026",
},
{
name: "DateEU",
format: DateEU,
want: "08/02/2026",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.format.Format(testTime)
if got != tt.want {
t.Errorf("Format() = %q, want %q", got, tt.want)
}
})
}
}