|
| 1 | +// Package xtime provides functionality for working with time. |
| 2 | +// |
| 3 | +// # Duration Formatting (FormatDuration) |
| 4 | +// |
| 5 | +// The FormatDuration function converts a time.Duration into a string composed |
| 6 | +// of multiple time units (e.g., "1h 5m 30s", "2 days, 3 hours"). This offers |
| 7 | +// more detailed breakdowns than the standard time.Duration.String() method, |
| 8 | +// which typically scales to the largest appropriate single unit (e.g., |
| 9 | +// "1m30.5s"). |
| 10 | +// |
| 11 | +// duration := 2*xtime.Day + 3*time.Hour + 15*time.Minute + 30*time.Second + |
| 12 | +// 500*time.Millisecond |
| 13 | +// |
| 14 | +// Default formatting (short style, max unit Day, min unit Second, no |
| 15 | +// rounding): |
| 16 | +// |
| 17 | +// fmt.Println(xtime.FormatDuration(duration)) // Output: 2d 3h 15m 30s |
| 18 | +// |
| 19 | +// ## Custom formatting examples |
| 20 | +// |
| 21 | +// Long style, max 2 components, rounding enabled: |
| 22 | +// |
| 23 | +// fmt.Println(xtime.FormatDuration(duration, |
| 24 | +// xtime.WithStyle(xtime.FormatStyleLong), |
| 25 | +// xtime.WithMaxComponents(2), |
| 26 | +// xtime.WithRounding(), |
| 27 | +// )) // Output: 2 days, 3 hours |
| 28 | +// |
| 29 | +// Compact style: |
| 30 | +// |
| 31 | +// fmt.Println(xtime.FormatDuration(duration, |
| 32 | +// xtime.WithStyle(xtime.FormatStyleCompact), |
| 33 | +// )) // Output: 2d3h |
| 34 | +// |
| 35 | +// Short style, rounding enabled, only seconds and smaller displayed: |
| 36 | +// |
| 37 | +// fmt.Println(xtime.FormatDuration(time.Second+600*time.Millisecond, |
| 38 | +// xtime.WithRounding(), |
| 39 | +// xtime.WithMinUnit(time.Millisecond), |
| 40 | +// )) // Output: 2s (Original: 1s 600ms, rounded up) |
| 41 | +// |
| 42 | +// Formatting Options (Functional Options Pattern): |
| 43 | +// - WithMaxUnit(unit time.Duration): Sets the largest unit for decomposition |
| 44 | +// (default: Day). |
| 45 | +// - WithMinUnit(unit time.Duration): Sets the smallest unit to display |
| 46 | +// (default: Second). Remainder is truncated or rounded. |
| 47 | +// - WithRounding(): Enables rounding of the MinUnit based on the remainder. |
| 48 | +// The duration is adjusted by adding half of MinUnit before decomposition. |
| 49 | +// - WithoutRounding(): Disables rounding (default). Remainder is truncated. |
| 50 | +// - WithMaxComponents(n int): Limits output to at most 'n' components |
| 51 | +// (default: 0 = unlimited). |
| 52 | +// - WithStyle(style FormatStyle): Sets output style (short, long, long-and). |
| 53 | +// - WithSeparator(sep string): Custom separator between components (default |
| 54 | +// depends on style). |
| 55 | +// - WithConjunction(conj string): Custom conjunction (" and " by default) |
| 56 | +// used before the last component in "long-and" style. |
| 57 | +// |
| 58 | +// # Duration Parsing (ParseDuration) |
| 59 | +// |
| 60 | +// The ParseDuration function converts a human-readable string representation |
| 61 | +// into a time.Duration value. It accepts various formats, including combined |
| 62 | +// units and common abbreviations. |
| 63 | +// |
| 64 | +// d1, err := xtime.ParseDuration("1h 30m 15s") |
| 65 | +// d2, err := xtime.ParseDuration("1.5hours 10sec") // Combined number/unit and spaces work |
| 66 | +// d3, err := xtime.ParseDuration("10 years, 2 months, 5 days") // Approximate units allowed |
| 67 | +// d4, err := xtime.ParseDuration("3d12h") |
| 68 | +// |
| 69 | +// Input String Processing: |
| 70 | +// 1. Cleaning: Leading/trailing whitespace is trimmed, "and " sequences are |
| 71 | +// removed, and commas are replaced with spaces. |
| 72 | +// 2. Tokenization: The cleaned string is split by spaces. Tokens containing |
| 73 | +// both numbers and letters (e.g., "10years", "1h30m", "h1") are further |
| 74 | +// split into number and unit parts (e.g., "10", "years", "1", "h", "30", |
| 75 | +// "m", "h", "1"). |
| 76 | +// 3. Parsing: |
| 77 | +// - If only one token results and it's a valid number, it's interpreted as |
| 78 | +// seconds. |
| 79 | +// - Otherwise, tokens are processed in pairs (value, unit). The value must |
| 80 | +// be a number (integer or float), and the unit must be one of the |
| 81 | +// recognized unit strings (e.g., "h", "hour", "hours", "d", "day", "days", |
| 82 | +// "mo", "month", "y", "year"). |
| 83 | +// - Parsing fails if the token sequence is invalid (e.g., odd number of |
| 84 | +// tokens, non-number where value is expected, unknown unit). |
| 85 | +// |
| 86 | +// Error Handling: |
| 87 | +// - Returns a specific error type (*DurationParseError) containing details |
| 88 | +// about the failure, including the original input, problematic token, and index. |
| 89 | +// |
| 90 | +// # Units and Approximations |
| 91 | +// |
| 92 | +// The package defines standard fixed-duration units (Week, Day) and also |
| 93 | +// provides approximate average durations for Month (MonthApprox) and Year |
| 94 | +// (YearApprox) based on the Gregorian calendar average (365.2425 days/year). |
| 95 | +// |
| 96 | +// The YearsFromDuration(d time.Duration) function converts a duration to an |
| 97 | +// approximate number of years using YearApprox. Useful for rough estimations |
| 98 | +// only. |
| 99 | +// |
| 100 | +// Note on Units Discrepancy: ParseDuration can parse approximate units like |
| 101 | +// "month" (mo) and "year" (y) based on the average durations (MonthApprox, |
| 102 | +// YearApprox). However, FormatDuration does not format durations using these |
| 103 | +// approximate units; it will decompose them into weeks, days, etc., for more |
| 104 | +// precise representation based on the fixed time.Duration value. |
| 105 | +// |
| 106 | +// Note: For calendar-accurate calculations involving months and years (which |
| 107 | +// vary in length), always operate on time.Time values using functions like |
| 108 | +// time.AddDate and time.Sub, rather than relying solely on time.Duration |
| 109 | +// arithmetic. |
| 110 | +package xtime |
0 commit comments