mirror of
https://github.com/binwiederhier/ntfy.git
synced 2025-11-28 03:12:26 +01:00
240 lines
6.8 KiB
Go
240 lines
6.8 KiB
Go
package sprig
|
|
|
|
import (
|
|
"math"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// date formats a date according to the provided format string.
|
|
//
|
|
// Parameters:
|
|
// - fmt: A Go time format string (e.g., "2006-01-02 15:04:05")
|
|
// - date: Can be a time.Time, *time.Time, or int/int32/int64 (seconds since UNIX epoch)
|
|
//
|
|
// If date is not one of the recognized types, the current time is used.
|
|
//
|
|
// Example usage in templates: {{ now | date "2006-01-02" }}
|
|
func date(fmt string, date any) string {
|
|
return dateInZone(fmt, date, "Local")
|
|
}
|
|
|
|
// htmlDate formats a date in HTML5 date format (YYYY-MM-DD).
|
|
//
|
|
// Parameters:
|
|
// - date: Can be a time.Time, *time.Time, or int/int32/int64 (seconds since UNIX epoch)
|
|
//
|
|
// If date is not one of the recognized types, the current time is used.
|
|
//
|
|
// Example usage in templates: {{ now | htmlDate }}
|
|
func htmlDate(date any) string {
|
|
return dateInZone("2006-01-02", date, "Local")
|
|
}
|
|
|
|
// htmlDateInZone formats a date in HTML5 date format (YYYY-MM-DD) in the specified timezone.
|
|
//
|
|
// Parameters:
|
|
// - date: Can be a time.Time, *time.Time, or int/int32/int64 (seconds since UNIX epoch)
|
|
// - zone: Timezone name (e.g., "UTC", "America/New_York")
|
|
//
|
|
// If date is not one of the recognized types, the current time is used.
|
|
// If the timezone is invalid, UTC is used.
|
|
//
|
|
// Example usage in templates: {{ now | htmlDateInZone "UTC" }}
|
|
func htmlDateInZone(date any, zone string) string {
|
|
return dateInZone("2006-01-02", date, zone)
|
|
}
|
|
|
|
// dateInZone formats a date according to the provided format string in the specified timezone.
|
|
//
|
|
// Parameters:
|
|
// - fmt: A Go time format string (e.g., "2006-01-02 15:04:05")
|
|
// - date: Can be a time.Time, *time.Time, or int/int32/int64 (seconds since UNIX epoch)
|
|
// - zone: Timezone name (e.g., "UTC", "America/New_York")
|
|
//
|
|
// If date is not one of the recognized types, the current time is used.
|
|
// If the timezone is invalid, UTC is used.
|
|
//
|
|
// Example usage in templates: {{ now | dateInZone "2006-01-02 15:04:05" "UTC" }}
|
|
func dateInZone(fmt string, date any, zone string) string {
|
|
var t time.Time
|
|
switch date := date.(type) {
|
|
default:
|
|
t = time.Now()
|
|
case time.Time:
|
|
t = date
|
|
case *time.Time:
|
|
t = *date
|
|
case int64:
|
|
t = time.Unix(date, 0)
|
|
case int:
|
|
t = time.Unix(int64(date), 0)
|
|
case int32:
|
|
t = time.Unix(int64(date), 0)
|
|
}
|
|
loc, err := time.LoadLocation(zone)
|
|
if err != nil {
|
|
loc, _ = time.LoadLocation("UTC")
|
|
}
|
|
return t.In(loc).Format(fmt)
|
|
}
|
|
|
|
// dateModify modifies a date by adding a duration and returns the resulting time.
|
|
//
|
|
// Parameters:
|
|
// - fmt: A duration string (e.g., "24h", "-12h30m", "1h15m30s")
|
|
// - date: The time.Time to modify
|
|
//
|
|
// If the duration string is invalid, the original date is returned.
|
|
//
|
|
// Example usage in templates: {{ now | dateModify "-24h" }}
|
|
func dateModify(fmt string, date time.Time) time.Time {
|
|
d, err := time.ParseDuration(fmt)
|
|
if err != nil {
|
|
return date
|
|
}
|
|
return date.Add(d)
|
|
}
|
|
|
|
// mustDateModify modifies a date by adding a duration and returns the resulting time or an error.
|
|
//
|
|
// Parameters:
|
|
// - fmt: A duration string (e.g., "24h", "-12h30m", "1h15m30s")
|
|
// - date: The time.Time to modify
|
|
//
|
|
// Unlike dateModify, this function returns an error if the duration string is invalid.
|
|
//
|
|
// Example usage in templates: {{ now | mustDateModify "24h" }}
|
|
func mustDateModify(fmt string, date time.Time) (time.Time, error) {
|
|
d, err := time.ParseDuration(fmt)
|
|
if err != nil {
|
|
return time.Time{}, err
|
|
}
|
|
return date.Add(d), nil
|
|
}
|
|
|
|
// dateAgo returns a string representing the time elapsed since the given date.
|
|
//
|
|
// Parameters:
|
|
// - date: Can be a time.Time, int, or int64 (seconds since UNIX epoch)
|
|
//
|
|
// If date is not one of the recognized types, the current time is used.
|
|
//
|
|
// Example usage in templates: {{ "2023-01-01" | toDate "2006-01-02" | dateAgo }}
|
|
func dateAgo(date any) string {
|
|
var t time.Time
|
|
switch date := date.(type) {
|
|
default:
|
|
t = time.Now()
|
|
case time.Time:
|
|
t = date
|
|
case int64:
|
|
t = time.Unix(date, 0)
|
|
case int:
|
|
t = time.Unix(int64(date), 0)
|
|
}
|
|
return time.Since(t).Round(time.Second).String()
|
|
}
|
|
|
|
// duration converts seconds to a duration string.
|
|
//
|
|
// Parameters:
|
|
// - sec: Can be a string (parsed as int64), or int64 representing seconds
|
|
//
|
|
// Example usage in templates: {{ 3600 | duration }} -> "1h0m0s"
|
|
func duration(sec any) string {
|
|
var n int64
|
|
switch value := sec.(type) {
|
|
default:
|
|
n = 0
|
|
case string:
|
|
n, _ = strconv.ParseInt(value, 10, 64)
|
|
case int64:
|
|
n = value
|
|
}
|
|
return (time.Duration(n) * time.Second).String()
|
|
}
|
|
|
|
// durationRound formats a duration in a human-readable rounded format.
|
|
//
|
|
// Parameters:
|
|
// - duration: Can be a string (parsed as duration), int64 (nanoseconds),
|
|
// or time.Time (time since that moment)
|
|
//
|
|
// Returns a string with the largest appropriate unit (y, mo, d, h, m, s).
|
|
//
|
|
// Example usage in templates: {{ 3600 | duration | durationRound }} -> "1h"
|
|
func durationRound(duration any) string {
|
|
var d time.Duration
|
|
switch duration := duration.(type) {
|
|
default:
|
|
d = 0
|
|
case string:
|
|
d, _ = time.ParseDuration(duration)
|
|
case int64:
|
|
d = time.Duration(duration)
|
|
case time.Time:
|
|
d = time.Since(duration)
|
|
}
|
|
u := uint64(math.Abs(float64(d)))
|
|
var (
|
|
year = uint64(time.Hour) * 24 * 365
|
|
month = uint64(time.Hour) * 24 * 30
|
|
day = uint64(time.Hour) * 24
|
|
hour = uint64(time.Hour)
|
|
minute = uint64(time.Minute)
|
|
second = uint64(time.Second)
|
|
)
|
|
switch {
|
|
case u > year:
|
|
return strconv.FormatUint(u/year, 10) + "y"
|
|
case u > month:
|
|
return strconv.FormatUint(u/month, 10) + "mo"
|
|
case u > day:
|
|
return strconv.FormatUint(u/day, 10) + "d"
|
|
case u > hour:
|
|
return strconv.FormatUint(u/hour, 10) + "h"
|
|
case u > minute:
|
|
return strconv.FormatUint(u/minute, 10) + "m"
|
|
case u > second:
|
|
return strconv.FormatUint(u/second, 10) + "s"
|
|
}
|
|
return "0s"
|
|
}
|
|
|
|
// toDate parses a string into a time.Time using the specified format.
|
|
//
|
|
// Parameters:
|
|
// - fmt: A Go time format string (e.g., "2006-01-02")
|
|
// - str: The date string to parse
|
|
//
|
|
// If parsing fails, returns a zero time.Time.
|
|
//
|
|
// Example usage in templates: {{ "2023-01-01" | toDate "2006-01-02" }}
|
|
func toDate(fmt, str string) time.Time {
|
|
t, _ := time.ParseInLocation(fmt, str, time.Local)
|
|
return t
|
|
}
|
|
|
|
// mustToDate parses a string into a time.Time using the specified format or returns an error.
|
|
//
|
|
// Parameters:
|
|
// - fmt: A Go time format string (e.g., "2006-01-02")
|
|
// - str: The date string to parse
|
|
//
|
|
// Unlike toDate, this function returns an error if parsing fails.
|
|
//
|
|
// Example usage in templates: {{ mustToDate "2006-01-02" "2023-01-01" }}
|
|
func mustToDate(fmt, str string) (time.Time, error) {
|
|
return time.ParseInLocation(fmt, str, time.Local)
|
|
}
|
|
|
|
// unixEpoch returns the Unix timestamp (seconds since January 1, 1970 UTC) for the given time.
|
|
//
|
|
// Parameters:
|
|
// - date: A time.Time value
|
|
//
|
|
// Example usage in templates: {{ now | unixEpoch }}
|
|
func unixEpoch(date time.Time) string {
|
|
return strconv.FormatInt(date.Unix(), 10)
|
|
}
|