Skip to content

Commit af6bc87

Browse files
committed
bake: add unixtimestampparse function
Signed-off-by: CrazyMax <[email protected]>
1 parent a6e198a commit af6bc87

File tree

3 files changed

+267
-110
lines changed

3 files changed

+267
-110
lines changed

bake/hclparser/stdlib.go

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ var stdlibFunctions = []funcDef{
127127
{name: "trimspace", fn: stdlib.TrimSpaceFunc},
128128
{name: "trimsuffix", fn: stdlib.TrimSuffixFunc},
129129
{name: "try", fn: tryfunc.TryFunc, descriptionAlt: `Variadic function that tries to evaluate all of is arguments in sequence until one succeeds, in which case it returns that result, or returns an error if none of them succeed.`},
130+
{name: "unixtimestampparse", factory: unixtimestampParseFunc},
130131
{name: "upper", fn: stdlib.UpperFunc},
131132
{name: "urlencode", fn: encoding.URLEncodeFunc, descriptionAlt: `Applies URL encoding to a given string.`},
132133
{name: "uuidv4", fn: uuid.V4Func, descriptionAlt: `Generates and returns a Type-4 UUID in the standard hexadecimal string format.`},
@@ -248,7 +249,7 @@ func sanitizeFunc() function.Function {
248249

249250
// timestampFunc constructs a function that returns a string representation of the current date and time.
250251
//
251-
// This function was imported from terraform's datetime utilities.
252+
// This function was imported from Terraform's datetime utilities.
252253
func timestampFunc() function.Function {
253254
return function.New(&function.Spec{
254255
Description: `Returns a string representation of the current date and time.`,
@@ -281,6 +282,59 @@ func homedirFunc() function.Function {
281282
})
282283
}
283284

285+
// unixtimestampParseFunc, given a unix timestamp integer, will parse and
286+
// return an object representation of that date and time
287+
//
288+
// This function is similar to the `unix_timestamp_parse` function in Terraform:
289+
// https://registry.terraform.io/providers/hashicorp/time/latest/docs/functions/unix_timestamp_parse
290+
func unixtimestampParseFunc() function.Function {
291+
return function.New(&function.Spec{
292+
Description: `Given a unix timestamp integer, will parse and return an object representation of that date and time. A unix timestamp is the number of seconds elapsed since January 1, 1970 UTC.`,
293+
Params: []function.Parameter{
294+
{
295+
Name: "unix_timestamp",
296+
Description: "Unix Timestamp integer to parse",
297+
Type: cty.Number,
298+
},
299+
},
300+
Type: function.StaticReturnType(cty.Object(map[string]cty.Type{
301+
"year": cty.Number,
302+
"year_day": cty.Number,
303+
"day": cty.Number,
304+
"month": cty.Number,
305+
"month_name": cty.String,
306+
"weekday": cty.Number,
307+
"weekday_name": cty.String,
308+
"hour": cty.Number,
309+
"minute": cty.Number,
310+
"second": cty.Number,
311+
"rfc3339": cty.String,
312+
"iso_year": cty.Number,
313+
"iso_week": cty.Number,
314+
})),
315+
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
316+
ts, _ := args[0].AsBigFloat().Int64()
317+
unixTime := time.Unix(ts, 0).UTC()
318+
isoYear, isoWeek := unixTime.ISOWeek()
319+
return cty.ObjectVal(map[string]cty.Value{
320+
"year": cty.NumberIntVal(int64(unixTime.Year())),
321+
"year_day": cty.NumberIntVal(int64(unixTime.YearDay())),
322+
"day": cty.NumberIntVal(int64(unixTime.Day())),
323+
"month": cty.NumberIntVal(int64(unixTime.Month())),
324+
"month_name": cty.StringVal(unixTime.Month().String()),
325+
"weekday": cty.NumberIntVal(int64(unixTime.Weekday())),
326+
"weekday_name": cty.StringVal(unixTime.Weekday().String()),
327+
"hour": cty.NumberIntVal(int64(unixTime.Hour())),
328+
"minute": cty.NumberIntVal(int64(unixTime.Minute())),
329+
"second": cty.NumberIntVal(int64(unixTime.Second())),
330+
"rfc3339": cty.StringVal(unixTime.Format(time.RFC3339)),
331+
"iso_year": cty.NumberIntVal(int64(isoYear)),
332+
"iso_week": cty.NumberIntVal(int64(isoWeek)),
333+
}), nil
334+
},
335+
})
336+
}
337+
284338
func Stdlib() map[string]function.Function {
285339
funcs := make(map[string]function.Function, len(stdlibFunctions))
286340
for _, v := range stdlibFunctions {

bake/hclparser/stdlib_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,29 @@ func TestHomedir(t *testing.T) {
205205
require.NotEmpty(t, home.AsString())
206206
require.True(t, filepath.IsAbs(home.AsString()))
207207
}
208+
209+
func TestUnixTimestampParseFunc(t *testing.T) {
210+
fn := unixtimestampParseFunc()
211+
input := cty.NumberIntVal(1690328596)
212+
got, err := fn.Call([]cty.Value{input})
213+
require.NoError(t, err)
214+
215+
expected := map[string]cty.Value{
216+
"year": cty.NumberIntVal(2023),
217+
"year_day": cty.NumberIntVal(206),
218+
"day": cty.NumberIntVal(25),
219+
"month": cty.NumberIntVal(7),
220+
"month_name": cty.StringVal("July"),
221+
"weekday": cty.NumberIntVal(2),
222+
"weekday_name": cty.StringVal("Tuesday"),
223+
"hour": cty.NumberIntVal(23),
224+
"minute": cty.NumberIntVal(43),
225+
"second": cty.NumberIntVal(16),
226+
"rfc3339": cty.StringVal("2023-07-25T23:43:16Z"),
227+
"iso_year": cty.NumberIntVal(2023),
228+
"iso_week": cty.NumberIntVal(30),
229+
}
230+
for k, v := range expected {
231+
require.True(t, got.GetAttr(k).RawEquals(v), "field %s: got %v, want %v", k, got.GetAttr(k), v)
232+
}
233+
}

0 commit comments

Comments
 (0)