or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

byte-sizes.mdenglish.mdindex.mdnumber-formatting.mdordinals.mdsi-notation.mdtime-formatting.md
tile.json

time-formatting.mddocs/

Time Formatting

Converts time.Time values into relative time expressions like "3 days ago", "2 weeks from now", or custom formats with configurable labels and magnitude thresholds.

Import

import (
	"time"
	"github.com/dustin/go-humanize"
)

Basic Relative Time

Time

func Time(then time.Time) string

Formats a time as a relative string from the current time using default labels ("ago" for past, "from now" for future).

Parameters:

  • then - The time to format

Returns: Relative time string like "3 weeks ago", "5 minutes from now"

Example:

past := time.Now().Add(-3 * time.Hour)
humanize.Time(past)  // "3 hours ago"

future := time.Now().Add(2 * time.Hour)
humanize.Time(future)  // 2 hours from now"

longAgo := time.Now().Add(-45 * 24 * time.Hour)
humanize.Time(longAgo)  // "1 month ago"

Custom Relative Time

RelTime

func RelTime(a, b time.Time, albl, blbl string) string

Formats the time difference between two times with custom labels. The label for the earlier time is applied to the result.

Parameters:

  • a - First time
  • b - Second time
  • albl - Label to use if a is earlier than b
  • blbl - Label to use if b is earlier than a

Returns: Relative time string with the appropriate label

Example:

earlier := time.Now().Add(-3 * time.Hour)
later := time.Now()

humanize.RelTime(earlier, later, "earlier", "later")  // "3 hours earlier"
humanize.RelTime(later, earlier, "earlier", "later")  // "3 hours later"

// Custom labels for specific contexts
start := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)
end := time.Date(2024, 1, 15, 0, 0, 0, 0, time.UTC)
humanize.RelTime(start, end, "before", "after")  // "2 weeks before"

CustomRelTime

func CustomRelTime(a, b time.Time, albl, blbl string, magnitudes []RelTimeMagnitude) string

Formats the time difference between two times with custom labels and custom magnitude thresholds. Allows full control over how different time ranges are formatted.

Parameters:

  • a - First time
  • b - Second time
  • albl - Label to use if a is earlier than b
  • blbl - Label to use if b is earlier than a
  • magnitudes - Slice of RelTimeMagnitude defining format rules for different time ranges

Returns: Relative time string formatted according to the magnitude rules

Example:

// Define custom magnitude thresholds
magnitudes := []humanize.RelTimeMagnitude{
	{time.Second, "just now", time.Second},
	{time.Minute, "%d seconds %s", time.Second},
	{time.Hour, "%d minutes %s", time.Minute},
	{24 * time.Hour, "%d hours %s", time.Hour},
	{7 * 24 * time.Hour, "%d days %s", 24 * time.Hour},
	{30 * 24 * time.Hour, "%d weeks %s", 7 * 24 * time.Hour},
	{365 * 24 * time.Hour, "%d months %s", 30 * 24 * time.Hour},
}

past := time.Now().Add(-90 * time.Second)
humanize.CustomRelTime(past, time.Now(), "ago", "from now", magnitudes)
// "1 minutes ago" (uses the minute threshold)

Types

RelTimeMagnitude

type RelTimeMagnitude struct {
	D      time.Duration  // Threshold duration for this magnitude
	Format string         // Format string with %s (label) and %d (quantity)
	DivBy  time.Duration  // Duration to divide by for display
}

Configuration for custom relative time formatting. Each magnitude defines a threshold duration, a format string, and a divisor.

Fields:

  • D - The duration threshold at which this format applies
  • Format - Format string that may contain %s (replaced with label) and %d (replaced with quantity)
  • DivBy - The duration to divide the time difference by to get the quantity

Example:

// Format times between 1 minute and 1 hour as "X minutes ago/from now"
magnitude := humanize.RelTimeMagnitude{
	D:      time.Hour,           // Apply until 1 hour
	Format: "%d minutes %s",     // Format with quantity and label
	DivBy:  time.Minute,         // Divide difference by 1 minute to get quantity
}

// Example magnitude table for precise control
magnitudes := []humanize.RelTimeMagnitude{
	{time.Second, "just now", time.Second},
	{2 * time.Second, "1 second %s", time.Second},
	{time.Minute, "%d seconds %s", time.Second},
	{2 * time.Minute, "1 minute %s", time.Minute},
	{time.Hour, "%d minutes %s", time.Minute},
	{2 * time.Hour, "1 hour %s", time.Hour},
	{humanize.Day, "%d hours %s", time.Hour},
	{2 * humanize.Day, "1 day %s", humanize.Day},
	{humanize.Week, "%d days %s", humanize.Day},
	{2 * humanize.Week, "1 week %s", humanize.Week},
	{humanize.Month, "%d weeks %s", humanize.Week},
	{2 * humanize.Month, "1 month %s", humanize.Month},
	{humanize.Year, "%d months %s", humanize.Month},
	{18 * humanize.Month, "1 year %s", humanize.Year},
	{2 * humanize.Year, "2 years %s", humanize.Year},
	{humanize.LongTime, "%d years %s", humanize.Year},
	{math.MaxInt64, "a long while %s", time.Second},
}

Time Constants

The package provides convenient time duration constants:

const (
	Day      = 24 * time.Hour
	Week     = 7 * Day
	Month    = 30 * Day
	Year     = 12 * Month
	LongTime = 37 * Year
)

Example:

// Use constants for calculations
pastMonth := time.Now().Add(-humanize.Month)
humanize.Time(pastMonth)  // "1 month ago"

nextWeek := time.Now().Add(humanize.Week)
humanize.Time(nextWeek)  // "1 week from now"

Common Use Cases

Activity Timestamps

lastSeen := time.Now().Add(-45 * time.Minute)
fmt.Printf("Last seen: %s", humanize.Time(lastSeen))
// Output: "Last seen: 45 minutes ago"

Event Scheduling

eventTime := time.Now().Add(3 * 24 * time.Hour)
fmt.Printf("Event starts: %s", humanize.Time(eventTime))
// Output: "Event starts: 3 days from now"

Comparing Two Dates

created := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)
modified := time.Date(2024, 1, 15, 10, 30, 0, 0, time.UTC)

fmt.Printf("Modified %s creation",
	humanize.RelTime(created, modified, "before", "after"))
// Output: "Modified 2 weeks after creation"

Custom Format for Specific Domain

// Gaming context: show respawn timer
respawnTime := time.Now().Add(30 * time.Second)
magnitudes := []humanize.RelTimeMagnitude{
	{time.Minute, "%d seconds until respawn", time.Second},
	{5 * time.Minute, "%d minutes until respawn", time.Minute},
}

message := humanize.CustomRelTime(time.Now(), respawnTime, "", "", magnitudes)
// "30 seconds until respawn"

Notes

  • The default Time() function uses the current time from time.Now() as the reference point
  • Time differences less than 1 second are typically displayed as "now" or "just now"
  • The functions automatically handle past vs future times and apply the appropriate label
  • Month is approximated as 30 days, Year as 365 days (12 * 30 days)
  • For very long time periods (> 37 years), the formatting switches to "a long while ago/from now"