xtime

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 23, 2025 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package xtime provides functionality for working with time.

Duration Formatting (FormatDuration)

The FormatDuration function converts a time.Duration into a string composed of multiple time units (e.g., "1h 5m 30s", "2 days, 3 hours"). This offers more detailed breakdowns than the standard time.Duration.String() method, which typically scales to the largest appropriate single unit (e.g., "1m30.5s").

duration := 2*xtime.Day + 3*time.Hour + 15*time.Minute + 30*time.Second +
			500*time.Millisecond

Default formatting (short style, max unit Day, min unit Second, no rounding):

fmt.Println(xtime.FormatDuration(duration)) // Output: 2d 3h 15m 30s

## Custom formatting examples

Long style, max 2 components, rounding enabled:

fmt.Println(xtime.FormatDuration(duration,
	xtime.WithStyle(xtime.FormatStyleLong),
	xtime.WithMaxComponents(2),
	xtime.WithRounding(),
)) // Output: 2 days, 3 hours

Compact style:

fmt.Println(xtime.FormatDuration(duration,
	xtime.WithStyle(xtime.FormatStyleCompact),
)) // Output: 2d3h

Short style, rounding enabled, only seconds and smaller displayed:

fmt.Println(xtime.FormatDuration(time.Second+600*time.Millisecond,
	xtime.WithRounding(),
	xtime.WithMinUnit(time.Millisecond),
)) // Output: 2s (Original: 1s 600ms, rounded up)

Formatting Options (Functional Options Pattern):

  • WithMaxUnit(unit time.Duration): Sets the largest unit for decomposition (default: Day).
  • WithMinUnit(unit time.Duration): Sets the smallest unit to display (default: Second). Remainder is truncated or rounded.
  • WithRounding(): Enables rounding of the MinUnit based on the remainder. The duration is adjusted by adding half of MinUnit before decomposition.
  • WithoutRounding(): Disables rounding (default). Remainder is truncated.
  • WithMaxComponents(n int): Limits output to at most 'n' components (default: 0 = unlimited).
  • WithStyle(style FormatStyle): Sets output style (short, long, long-and).
  • WithSeparator(sep string): Custom separator between components (default depends on style).
  • WithConjunction(conj string): Custom conjunction (" and " by default) used before the last component in "long-and" style.

Duration Parsing (ParseDuration)

The ParseDuration function converts a human-readable string representation into a time.Duration value. It accepts various formats, including combined units and common abbreviations.

d1, err := xtime.ParseDuration("1h 30m 15s")
d2, err := xtime.ParseDuration("1.5hours 10sec") // Combined number/unit and spaces work
d3, err := xtime.ParseDuration("10 years, 2 months, 5 days") // Approximate units allowed
d4, err := xtime.ParseDuration("3d12h")

Input String Processing:

  1. Cleaning: Leading/trailing whitespace is trimmed, "and " sequences are removed, and commas are replaced with spaces.
  2. Tokenization: The cleaned string is split by spaces. Tokens containing both numbers and letters (e.g., "10years", "1h30m", "h1") are further split into number and unit parts (e.g., "10", "years", "1", "h", "30", "m", "h", "1").
  3. Parsing: - If only one token results and it's a valid number, it's interpreted as seconds. - Otherwise, tokens are processed in pairs (value, unit). The value must be a number (integer or float), and the unit must be one of the recognized unit strings (e.g., "h", "hour", "hours", "d", "day", "days", "mo", "month", "y", "year"). - Parsing fails if the token sequence is invalid (e.g., odd number of tokens, non-number where value is expected, unknown unit).

Error Handling:

  • Returns a specific error type (*DurationParseError) containing details about the failure, including the original input, problematic token, and index.

Units and Approximations

The package defines standard fixed-duration units (Week, Day) and also provides approximate average durations for Month (MonthApprox) and Year (YearApprox) based on the Gregorian calendar average (365.2425 days/year).

The YearsFromDuration(d time.Duration) function converts a duration to an approximate number of years using YearApprox. Useful for rough estimations only.

Note on Units Discrepancy: ParseDuration can parse approximate units like "month" (mo) and "year" (y) based on the average durations (MonthApprox, YearApprox). However, FormatDuration does not format durations using these approximate units; it will decompose them into weeks, days, etc., for more precise representation based on the fixed time.Duration value.

Note: For calendar-accurate calculations involving months and years (which vary in length), always operate on time.Time values using functions like time.AddDate and time.Sub, rather than relying solely on time.Duration arithmetic.

Index

Constants

View Source
const (
	Day  time.Duration = 24 * time.Hour
	Week time.Duration = 7 * Day

	// YearApprox is the average duration of a year in the Gregorian calendar (365.2425 days).
	// Use this for approximations only; it does not account for calendar specifics.
	YearApprox time.Duration = time.Duration(365.2425 * float64(Day))

	// MonthApprox is the average duration of a month in the Gregorian calendar (30.436875 days).
	// Use this for approximations only; it does not account for calendar specifics.
	MonthApprox time.Duration = time.Duration(float64(YearApprox) / 12)
)

Variables

This section is empty.

Functions

func ApproxYearsFromDuration

func ApproxYearsFromDuration(d time.Duration) float64

ApproxYearsFromDuration converts a duration into an approximate number of years. It calculates this based on the average length of a year in the Gregorian calendar (365.2425 days).

WARNING: This function provides an estimation based on duration only. It does not account for specific calendar start/end dates, leap year occurrences within a specific period, or time zones. For calendar-accurate differences involving years and months, use functions operating on time.Time values.

func FormatDuration

func FormatDuration(d time.Duration, opts ...FormatOption) string

FormatDuration formats a duration into a human-readable string composed of multiple time units (e.g., "1h 5m 30s", "2 days, 3 hours").

Use FormatOptions functions (WithMaxUnit, WithMinUnit, WithRounding, WithMaxComponents, WithStyle, WithSeparator, WithConjunction) to customize output.

Example:

FormatDuration(90*time.Minute, WithStyle(FormatStyleLong)) // "1 hour, 30 minutes"
FormatDuration(3723*time.Second, WithMinUnit(time.Second), WithMaxComponents(2)) // "1h 2m"
FormatDuration(time.Second + 600*time.Millisecond, WithRounding()) // "2s"

func ParseDuration

func ParseDuration(s string) (time.Duration, error)

ParseDuration converts a human-readable duration string into a time.Duration.

It first cleans the input string using the clean() function (removing extra words like "and", replacing commas with spaces, trimming whitespace). Then, it tokenizes the cleaned string using the tokenize() function, which splits the string by spaces and also by transitions between numbers and letters (e.g., "1h30m" becomes ["1", "h", "30", "m"]).

The function handles the following cases:

  • Empty or whitespace-only input: Returns an error.
  • Single token input: Attempts to parse it as a float64 representing seconds. Returns an error if the token is not a valid number.
  • Multiple tokens: Expects an even number of tokens representing pairs of (value, unit). It iterates through these pairs, parses the value as a float64, looks up the unit in the predefined units map, and accumulates the total duration.

It returns an error if:

  • The input is empty after cleaning.
  • A single token cannot be parsed as a number.
  • There is an odd number of tokens (expecting pairs).
  • A token expected to be a value cannot be parsed as a float64.
  • A token expected to be a unit is not found in the units map.

Types

type DurationParseError

type DurationParseError struct {
	// The original input string that caused the error.
	Input string
	// The specific token that caused the error, if applicable.
	Token string
	// The index of the problematic token, if applicable.
	TokenIndex int
	// Description of the error.
	Message string
}

DurationParseError provides specific details about a duration parsing failure.

func (*DurationParseError) Error

func (e *DurationParseError) Error() string

type FormatOption

type FormatOption func(*FormatOptions)

FormatOption is a function type for setting format options.

func WithConjunction

func WithConjunction(conj string) FormatOption

WithConjunction sets the conjunction string for "long-and" style.

func WithMaxComponents

func WithMaxComponents(p int) FormatOption

WithMaxComponents sets the max number of components. 0 means unlimited.

func WithMaxUnit

func WithMaxUnit(unit time.Duration) FormatOption

WithMaxUnit sets the largest unit to display.

func WithMinUnit

func WithMinUnit(unit time.Duration) FormatOption

WithMinUnit sets the smallest unit to display.

func WithRounding

func WithRounding() FormatOption

WithRounding enables rounding of the MinUnit.

func WithSeparator

func WithSeparator(sep string) FormatOption

WithSeparator sets the separator string.

func WithStyle

func WithStyle(style FormatStyle) FormatOption

WithStyle sets the output style (short, long, long-and).

type FormatOptions

type FormatOptions struct {
	// MaxUnit is the largest time unit to display (e.g., time.Hour,
	// xtime.Day). Components larger than this will be represented in terms of
	// this unit.
	// Default: xtime.Day.
	MaxUnit time.Duration
	// MinUnit is the smallest time unit to display (e.g., time.Second,
	// time.Millisecond). Any remaining duration smaller than this will be
	// truncated or rounded depending on Rounding.
	// Default: time.Second.
	MinUnit time.Duration
	// Rounding enables rounding of the smallest displayed unit based on the
	// remainder.
	// If false (default), the remainder is truncated.
	Rounding bool
	// MaxComponents limits the maximum number of components displayed (e.g.,
	// 2 // might yield "1h 5m").
	// Set to 0 or negative for unlimited components (down to MinUnit).
	// Default: 0 (unlimited).
	MaxComponents int
	// Style determines the format of unit names (compact, short, long,
	// long-and).
	// Default: FormatStyleShort.
	Style FormatStyle
	// Separator is the string used between components (ignored if only one
	// component).
	// Default: ", " for long styles, " " for short style, "" for compact style.
	Separator string
	// Conjunction is the string used before the last component in "long-and"
	// style.
	// Default: " and ".
	Conjunction string
}

FormatOptions provides configuration for Format.

func DefaultFormatOptions

func DefaultFormatOptions() FormatOptions

DefaultFormatOptions creates options with default values.

type FormatStyle

type FormatStyle string

FormatStyle defines the output style for formatted durations.

const (
	// FormatStyleCompact uses abbreviated units without spaces ("1h5m30s").
	FormatStyleCompact FormatStyle = "compact"
	// FormatStyleShort uses abbreviated units ("1h 5m 30s").
	FormatStyleShort FormatStyle = "short"
	// FormatStyleLong uses full unit names ("1 hour, 5 minutes, 30 seconds").
	FormatStyleLong FormatStyle = "long"
	// FormatStyleLongAnd uses full names with "and" before the last component
	// ("1 hour, 5 minutes and 30 seconds").
	FormatStyleLongAnd FormatStyle = "long-and"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL