feat: implement date segment type for part number generation

Fixes #79

Implement the date segment type in the part number generator. Uses Go's
time.Format with the segment's Value field as the layout string.

- Default format: 20060102 (YYYYMMDD) when no Value is specified
- Custom formats via Value field: "0601" (YYMM), "2006" (YYYY), etc.
- Always uses UTC time
- Add 3 tests: default format, custom YYMM format, year-only format
This commit is contained in:
Forbes
2026-02-13 13:10:57 -06:00
parent 648c659e2b
commit 1f7960db50
2 changed files with 92 additions and 2 deletions

View File

@@ -6,6 +6,7 @@ import (
"fmt"
"regexp"
"strings"
"time"
"github.com/kindredsystems/silo/internal/schema"
)
@@ -99,8 +100,11 @@ func (g *Generator) resolveSegment(
return g.formatSerial(seg, next), nil
case "date":
// TODO: implement date formatting
return "", fmt.Errorf("date segments not yet implemented")
layout := seg.Value
if layout == "" {
layout = "20060102"
}
return time.Now().UTC().Format(layout), nil
default:
return "", fmt.Errorf("unknown segment type: %s", seg.Type)

View File

@@ -3,7 +3,9 @@ package partnum
import (
"context"
"fmt"
"regexp"
"testing"
"time"
"github.com/kindredsystems/silo/internal/schema"
)
@@ -165,3 +167,87 @@ func TestGenerateConstantSegment(t *testing.T) {
t.Errorf("got %q, want %q", pn, "KS-0001")
}
}
func TestGenerateDateSegmentDefault(t *testing.T) {
s := &schema.Schema{
Name: "date-test",
Version: 1,
Separator: "-",
Segments: []schema.Segment{
{Name: "date", Type: "date"},
{Name: "serial", Type: "serial", Length: 3},
},
}
gen := NewGenerator(map[string]*schema.Schema{"date-test": s}, &mockSeqStore{})
pn, err := gen.Generate(context.Background(), Input{
SchemaName: "date-test",
Values: map[string]string{},
})
if err != nil {
t.Fatalf("Generate returned error: %v", err)
}
// Default format: YYYYMMDD-NNN
want := time.Now().UTC().Format("20060102") + "-001"
if pn != want {
t.Errorf("got %q, want %q", pn, want)
}
}
func TestGenerateDateSegmentCustomFormat(t *testing.T) {
s := &schema.Schema{
Name: "date-custom",
Version: 1,
Separator: "-",
Segments: []schema.Segment{
{Name: "date", Type: "date", Value: "0601"},
{Name: "serial", Type: "serial", Length: 4},
},
}
gen := NewGenerator(map[string]*schema.Schema{"date-custom": s}, &mockSeqStore{})
pn, err := gen.Generate(context.Background(), Input{
SchemaName: "date-custom",
Values: map[string]string{},
})
if err != nil {
t.Fatalf("Generate returned error: %v", err)
}
// Format "0601" produces YYMM
if matched, _ := regexp.MatchString(`^\d{4}-\d{4}$`, pn); !matched {
t.Errorf("got %q, want pattern YYMM-NNNN", pn)
}
want := time.Now().UTC().Format("0601") + "-0001"
if pn != want {
t.Errorf("got %q, want %q", pn, want)
}
}
func TestGenerateDateSegmentYearOnly(t *testing.T) {
s := &schema.Schema{
Name: "date-year",
Version: 1,
Separator: "-",
Segments: []schema.Segment{
{Name: "year", Type: "date", Value: "2006"},
{Name: "serial", Type: "serial", Length: 4},
},
}
gen := NewGenerator(map[string]*schema.Schema{"date-year": s}, &mockSeqStore{})
pn, err := gen.Generate(context.Background(), Input{
SchemaName: "date-year",
Values: map[string]string{},
})
if err != nil {
t.Fatalf("Generate returned error: %v", err)
}
want := time.Now().UTC().Format("2006") + "-0001"
if pn != want {
t.Errorf("got %q, want %q", pn, want)
}
}