add date-from helper

pull/358/head
Karolis Pabijanskas 6 months ago
parent be1249d7a6
commit 3fd8073fce

@ -50,6 +50,15 @@ You can get a date object from a natural human date (e.g. `tomorrow`, `2 weeks a
{{format-date (date "last week") "timestamp"}}
```
#### Date from natural string helper, based on a reference date
You can also get a date object from a natural human date (e.g. `tomorrow`, `2 weeks ago`, `2022-03-24`), but from a given reference time, using the `{{date-from}}` helper. It is most useful when paired with the `{{format-date}}` helper.
```
{{ datefrom "2006-01-02" "1 day ago" }}
{{format-date (date-from "2006-01-02" "next monday") "timestamp"}}
```
#### Date formatting helper
The `{{format-date}}` helper formats the given date for display.

@ -17,6 +17,7 @@ func Init(supportsUTF8 bool, logger util.Logger) {
helpers.RegisterConcat()
helpers.RegisterDate(logger)
helpers.RegisterFormatDate(logger)
helpers.RegisterDateFrom(logger)
helpers.RegisterJoin()
helpers.RegisterJSON(logger)
helpers.RegisterList(supportsUTF8)

@ -66,6 +66,41 @@ func RegisterFormatDate(logger util.Logger) {
})
}
// RegisterDateFrom registers the {{date-from}} template helper to use the `naturaldate` package to generate time.Time based on language strings,
// based on a reference time which can also be a time string or a time.Time object.
// This can be used in combination with the `format-date` helper to generate dates in the user's language.
// {{format-date (date-from "2006-01-02" "last week") "timestamp"}}
//
// Format is: {{date-from "REFERENCE TIME" "NATURAL DATE TIMESTAMP"}}
// Reference Time can either be a time.Time object or a string. Parsing matches the {{date}} helper, but without natural language parsing
// Natural Date Timestamp behaves the same as the {{date}} helper, but uses the given reference time to offset the generated time.Time object.
func RegisterDateFrom(logger util.Logger) {
raymond.RegisterHelper("date-from", func(arg1 any, arg2 string) time.Time {
var refTime time.Time
switch ref := arg1.(type) {
case string:
var err error
refTime, err = dateutil.ParseTimestamp(ref)
if err != nil {
logger.Printf("the {{date-from}} template helper failed to parse the reference date: %v", err)
return refTime
}
case time.Time:
refTime = ref
default:
logger.Printf("the {{date-from}} template helper expects a date string ir a time object as its first argument")
return refTime
}
t, err := dateutil.TimeFromReference(arg2, refTime)
if err != nil {
logger.Err(errors.Wrap(err, "the {{date-from}} template helper failed to parse the date"))
}
return t
})
}
var (
shortFormat = `%m/%d/%Y`
mediumFormat = `%b %d, %Y`

@ -1,6 +1,7 @@
package date
import (
"fmt"
"time"
naturaldate "github.com/tj/go-naturaldate"
@ -37,6 +38,20 @@ func (n *Frozen) Date() time.Time {
// TimeFromNatural parses a human date into a time.Time.
func TimeFromNatural(date string) (time.Time, error) {
if t, err := ParseTimestamp(date); err == nil {
return t, nil
}
return naturaldate.Parse(date, time.Now(), naturaldate.WithDirection(naturaldate.Past))
}
func TimeFromReference(date string, refTime time.Time) (time.Time, error) {
if t, err := ParseTimestamp(date); err == nil {
return t, nil
}
return naturaldate.Parse(date, refTime, naturaldate.WithDirection(naturaldate.Past))
}
func ParseTimestamp(date string) (time.Time, error) {
if date == "" {
return time.Now(), nil
}
@ -61,5 +76,5 @@ func TimeFromNatural(date string) (time.Time, error) {
if t, err := time.ParseInLocation("15:04", date, time.Local); err == nil {
return t, nil
}
return naturaldate.Parse(date, time.Now(), naturaldate.WithDirection(naturaldate.Past))
return time.Time{}, fmt.Errorf("unable to parse reference time '%s'", date)
}

Loading…
Cancel
Save