From 2c6b14d52d8bc8587196cac166f0ecba6d6f458f Mon Sep 17 00:00:00 2001 From: Marcel van Lohuizen Date: Fri, 18 Feb 2022 16:14:30 +0100 Subject: [PATCH] pkg/time: add FormatString and Split Down the line, FormatString should replace Format with new semantics. It is added now as FormatString to aid in the transition. Issue #1508 Change-Id: I1d80aab593a7e8b18dd500d73aef12fb9e5bfa4b Signed-off-by: Marcel van Lohuizen --- pkg/time/pkg.go | 25 ++++++++++++++++++++ pkg/time/testdata/gen.txtar | 14 +++++++++++ pkg/time/time.go | 46 +++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+) diff --git a/pkg/time/pkg.go b/pkg/time/pkg.go index 4e6c816fc0d..dd758654588 100644 --- a/pkg/time/pkg.go +++ b/pkg/time/pkg.go @@ -192,6 +192,19 @@ var pkg = &internal.Package{ c.Ret, c.Err = Format(value, layout) } }, + }, { + Name: "FormatString", + Params: []internal.Param{ + {Kind: adt.StringKind}, + {Kind: adt.StringKind}, + }, + Result: adt.StringKind, + Func: func(c *internal.CallCtxt) { + layout, value := c.String(0), c.String(1) + if c.Do() { + c.Ret, c.Err = FormatString(layout, value) + } + }, }, { Name: "Parse", Params: []internal.Param{ @@ -218,5 +231,17 @@ var pkg = &internal.Package{ c.Ret = Unix(sec, nsec) } }, + }, { + Name: "Split", + Params: []internal.Param{ + {Kind: adt.StringKind}, + }, + Result: adt.TopKind, + Func: func(c *internal.CallCtxt) { + t := c.String(0) + if c.Do() { + c.Ret, c.Err = Split(t) + } + }, }}, } diff --git a/pkg/time/testdata/gen.txtar b/pkg/time/testdata/gen.txtar index 0fe0e76431e..7547a2ac616 100644 --- a/pkg/time/testdata/gen.txtar +++ b/pkg/time/testdata/gen.txtar @@ -19,6 +19,9 @@ parse: { t2: time.Parse(_layout, _layout) } +split: { + t1: time.Split("2017-07-14T02:40:00.000123456Z") +} -- out/time -- Errors: t2: invalid value "no time" (does not satisfy time.Time): error in call to time.Time: invalid time "no time": @@ -32,4 +35,15 @@ parse: { t1: "2021-07-01T17:54:00Z" t2: "2006-01-02T22:04:05Z" } +split: { + t1: { + year: 2017 + month: 7 + day: 14 + hour: 2 + minute: 40 + second: 0 + nanosecond: 123456 + } +} diff --git a/pkg/time/time.go b/pkg/time/time.go index 5e068dce7cc..5c6c8698daf 100644 --- a/pkg/time/time.go +++ b/pkg/time/time.go @@ -13,6 +13,9 @@ // limitations under the License. // Package time defines time-related types. +// +// In CUE time values are represented as a string of the format +// time.RFC3339Nano. package time import ( @@ -146,6 +149,17 @@ func Format(value, layout string) (bool, error) { return timeFormat(value, layout) } +// FormatString returns a textual representation of the time value. +// The formatted value is formatted according to the layout defined by the +// argument. See Parse for more information on the layout string. +func FormatString(layout, value string) (string, error) { + t, err := time.Parse(time.RFC3339Nano, value) + if err != nil { + return "", err + } + return t.Format(layout), nil +} + // Parse parses a formatted string and returns the time value it represents. // The layout defines the format by showing how the reference time, // defined to be @@ -195,3 +209,35 @@ func Unix(sec int64, nsec int64) string { t := time.Unix(sec, nsec) return t.UTC().Format(time.RFC3339Nano) } + +// Parts holds individual parts of a parsed time stamp. +type Parts struct { + Year int `json:"year"` + Month int `json:"month"` + Day int `json:"day"` + Hour int `json:"hour"` + Minute int `json:"minute"` + + // Second is equal to div(Nanosecond, 1_000_000_000) + Second int `json:"second"` + Nanosecond int `json:"nanosecond"` +} + +// Split parses a time string into its individual parts. +func Split(t string) (*Parts, error) { + st, err := time.Parse(time.RFC3339Nano, t) + if err != nil { + return nil, err + } + year, month, day := st.Date() + return &Parts{ + Year: year, + Month: int(month), + Day: day, + Hour: st.Hour(), + Minute: st.Minute(), + + Second: st.Second(), + Nanosecond: st.Nanosecond(), + }, nil +}