summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorCameron Moore <[email protected]>2020-10-20 20:07:11 -0500
committerBjørn Erik Pedersen <[email protected]>2020-10-21 09:49:25 +0200
commit807db97af83ff61b022cbc8af80b9dc9cdb8dd43 (patch)
tree3b633d6bdfaccf7fca9bd1ca28b7d31947d5703d
parent26eeb2914720929d2d778f14d6a4bf737014e9e3 (diff)
downloadhugo-807db97af83ff61b022cbc8af80b9dc9cdb8dd43.tar.gz
hugo-807db97af83ff61b022cbc8af80b9dc9cdb8dd43.zip
tpl: Refactor time.AsTime location implementation
-rw-r--r--docs/content/en/functions/time.md12
-rw-r--r--tpl/time/time.go92
2 files changed, 50 insertions, 54 deletions
diff --git a/docs/content/en/functions/time.md b/docs/content/en/functions/time.md
index 57d5f65f8..c4f74215b 100644
--- a/docs/content/en/functions/time.md
+++ b/docs/content/en/functions/time.md
@@ -13,13 +13,13 @@ menu:
keywords: [dates,time,location]
signature: ["time INPUT [LOCATION]"]
workson: []
-hugoversion:
+hugoversion: "v0.77.0"
relatedfuncs: []
deprecated: false
aliases: []
---
-`time` converts a timestamp string with an optional timezone into a [`time.Time`](https://godoc.org/time#Time) structure so you can access its fields:
+`time` converts a timestamp string with an optional default location into a [`time.Time`](https://godoc.org/time#Time) structure so you can access its fields:
```
{{ time "2016-05-28" }} → "2016-05-28T00:00:00Z"
@@ -27,9 +27,11 @@ aliases: []
{{ mul 1000 (time "2016-05-28T10:30:00.00+10:00").Unix }} → 1464395400000, or Unix time in milliseconds
```
-## Using Timezone
+## Using Locations
-The optional 2nd parameter [LOCATION] argument is a string that references a timezone that is associated with the specified time value. If the time value has an explicit timezone or offset specified, it will take precedence over an explicit [LOCATION].
+The optional `LOCATION` parameter is a string that sets a default location that is associated with the specified time value. If the time value has an explicit timezone or offset specified, it will take precedence over the `LOCATION` parameter.
+
+The list of valid locations may be system dependent, but should include `UTC`, `Local`, or any location in the [IANA Time Zone database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
```
{{ time "2020-10-20" }} → 2020-10-20 00:00:00 +0000 UTC
@@ -37,8 +39,6 @@ The optional 2nd parameter [LOCATION] argument is a string that references a tim
{{ time "2020-01-20" "America/Los_Angeles" }} → 2020-01-20 00:00:00 -0800 PST
```
-> **Note**: Timezone support via the [LOCATION] parameter is included with Hugo `0.77`.
-
## Example: Using `time` to get Month Index
The following example takes a UNIX timestamp---set as `utimestamp: "1489276800"` in a content's front matter---converts the timestamp (string) to an integer using the [`int` function][int], and then uses [`printf`][] to convert the `Month` property of `time` into an index.
diff --git a/tpl/time/time.go b/tpl/time/time.go
index c3a01003a..8ed4606d6 100644
--- a/tpl/time/time.go
+++ b/tpl/time/time.go
@@ -21,6 +21,33 @@ import (
"github.com/spf13/cast"
)
+var timeFormats = []string{
+ _time.RFC3339,
+ "2006-01-02T15:04:05", // iso8601 without timezone
+ _time.RFC1123Z,
+ _time.RFC1123,
+ _time.RFC822Z,
+ _time.RFC822,
+ _time.RFC850,
+ _time.ANSIC,
+ _time.UnixDate,
+ _time.RubyDate,
+ "2006-01-02 15:04:05.999999999 -0700 MST", // Time.String()
+ "2006-01-02",
+ "02 Jan 2006",
+ "2006-01-02T15:04:05-0700", // RFC3339 without timezone hh:mm colon
+ "2006-01-02 15:04:05 -07:00",
+ "2006-01-02 15:04:05 -0700",
+ "2006-01-02 15:04:05Z07:00", // RFC3339 without T
+ "2006-01-02 15:04:05Z0700", // RFC3339 without T or timezone hh:mm colon
+ "2006-01-02 15:04:05",
+ _time.Kitchen,
+ _time.Stamp,
+ _time.StampMilli,
+ _time.StampMicro,
+ _time.StampNano,
+}
+
// New returns a new instance of the time-namespaced template functions.
func New() *Namespace {
return &Namespace{}
@@ -32,30 +59,26 @@ type Namespace struct{}
// AsTime converts the textual representation of the datetime string into
// a time.Time interface.
func (ns *Namespace) AsTime(v interface{}, args ...interface{}) (interface{}, error) {
- t, err := cast.ToTimeE(v)
- if err != nil {
- return nil, err
- }
-
if len(args) == 0 {
+ t, err := cast.ToTimeE(v)
+ if err != nil {
+ return nil, err
+ }
+
return t, nil
}
- // Otherwise, if a location is specified, attempt to parse the time using the location specified.
- // Note: In this case, we require the input variable to be a string for proper parsing.
- // Note: We can't convert an existing parsed time by using the `Time.In()` as this CONVERTS/MODIFIES
- // the resulting time.
-
- switch givenType := v.(type) {
- case string:
- // Good, we only support strings
- break
+ timeStr, err := cast.ToStringE(v)
+ if err != nil {
+ return nil, err
+ }
- default:
- return nil, fmt.Errorf("Creating a time instance with location requires a value of type String. Given type: %s", givenType)
+ locStr, err := cast.ToStringE(args[0])
+ if err != nil {
+ return nil, err
}
- location, err := _time.LoadLocation(args[0].(string))
+ loc, err := _time.LoadLocation(locStr)
if err != nil {
return nil, err
}
@@ -63,41 +86,14 @@ func (ns *Namespace) AsTime(v interface{}, args ...interface{}) (interface{}, er
// Note: Cast currently doesn't support time with non-default locations. For now, just inlining this.
// Reference: https://github.com/spf13/cast/pull/80
- fmts := []string{
- _time.RFC3339,
- "2006-01-02T15:04:05", // iso8601 without timezone
- _time.RFC1123Z,
- _time.RFC1123,
- _time.RFC822Z,
- _time.RFC822,
- _time.RFC850,
- _time.ANSIC,
- _time.UnixDate,
- _time.RubyDate,
- "2006-01-02 15:04:05.999999999 -0700 MST", // Time.String()
- "2006-01-02",
- "02 Jan 2006",
- "2006-01-02T15:04:05-0700", // RFC3339 without timezone hh:mm colon
- "2006-01-02 15:04:05 -07:00",
- "2006-01-02 15:04:05 -0700",
- "2006-01-02 15:04:05Z07:00", // RFC3339 without T
- "2006-01-02 15:04:05Z0700", // RFC3339 without T or timezone hh:mm colon
- "2006-01-02 15:04:05",
- _time.Kitchen,
- _time.Stamp,
- _time.StampMilli,
- _time.StampMicro,
- _time.StampNano,
- }
-
- for _, dateType := range fmts {
- t, err := _time.ParseInLocation(dateType, v.(string), location)
- if err == nil {
+ for _, dateType := range timeFormats {
+ t, err2 := _time.ParseInLocation(dateType, timeStr, loc)
+ if err2 == nil {
return t, nil
}
}
- return nil, fmt.Errorf("Unable to ParseInLocation using date \"%s\" with timezone \"%s\"", v, location)
+ return nil, fmt.Errorf("Unable to ParseInLocation using date %q with timezone %q", v, loc)
}
// Format converts the textual representation of the datetime string into