Date & Time Helper

The timex package is Nimbus's answer to Carbon (Laravel) and modern date libraries like Luxon. It wraps Go's time.Time in a fluent, chainable API for manipulation, comparison, and human-friendly output — no more manual AddDate() gymnastics.

Concept

NimbusTime wraps a standard time.Time value. Every mutator returns a new NimbusTime (immutable — the original is never modified), so you can chain mutations freely. Terminal methods like Time(), ToISO(), and DiffForHumans() extract the final value.

import "github.com/CodeSyncr/nimbus/timex"

// Trial expires 14 days from now, at 11:59 PM
expiresAt := timex.Now().AddDays(14).EndOfDay()
fmt.Println(expiresAt.ToDateTimeString()) // "2026-04-01 23:59:59"
fmt.Println(expiresAt.DiffForHumans())    // "in 14 days"

Entry Points

FunctionDescription
timex.Now()Current time
timex.Parse(s)Auto-detects RFC3339, datetime, or date format
timex.FromTime(t)Wrap an existing time.Time

Available Methods

Manipulation (Chainable)

MethodDescription
AddDays(n) / SubDays(n)Add or subtract days
AddHours(n) / SubHours(n)Add or subtract hours
AddMinutes(n) / SubMinutes(n)Add or subtract minutes
AddMonths(n) / SubMonths(n)Add or subtract months
AddYears(n) / SubYears(n)Add or subtract years
StartOfDay() / EndOfDay()Snap to midnight or 23:59:59
StartOfWeek() / EndOfWeek()Monday start / Sunday end
StartOfMonth() / EndOfMonth()First/last moment of the month
StartOfYear() / EndOfYear()Jan 1 midnight / Dec 31 end

Comparison (Terminal)

MethodReturnsDescription
IsBefore(other)boolIs before other time
IsAfter(other)boolIs after other time
IsSame(other)boolExact equality
IsBetween(start, end)boolFalls within a range
IsToday()boolSame calendar date as now
IsPast() / IsFuture()boolBefore/after current time
IsWeekend() / IsWeekday()boolSaturday/Sunday or Mon-Fri

Output (Terminal)

MethodExample Output
ToDateString()"2026-03-18"
ToTimeString()"15:04:05"
ToDateTimeString()"2026-03-18 15:04:05"
ToISO()"2026-03-18T15:04:05+05:30"
DiffForHumans()"3 days ago" / "in 2 hours"
DiffInDays(other)int — difference in days
DiffInHours(other)int — difference in hours
Unix()Unix timestamp (int64)
Time()Unwrap to time.Time

Real-Life Example: Subscription Trial Logic

func isTrialActive(user User) bool {
    trialEnd := timex.FromTime(user.CreatedAt).AddDays(14).EndOfDay()
    return trialEnd.IsFuture()
}

func daysLeftInTrial(user User) int {
    trialEnd := timex.FromTime(user.CreatedAt).AddDays(14).EndOfDay()
    return trialEnd.DiffInDays(timex.Now())
}

Real-Life Example: Weekly Report Date Ranges

func (ctrl *ReportController) Weekly(c *http.Context) error {
    weekStart := timex.Now().StartOfWeek()
    weekEnd := timex.Now().EndOfWeek()

    var orders []Order
    database.Get().
        Where("created_at BETWEEN ? AND ?", weekStart.Time(), weekEnd.Time()).
        Find(&orders)

    return c.JSON(200, map[string]any{
        "from":   weekStart.ToDateString(),
        "to":     weekEnd.ToDateString(),
        "orders": orders,
    })
}

Real-Life Example: Human-Friendly Timestamps in Templates

func (ctrl *PostController) Index(c *http.Context) error {
    var posts []Post
    database.Get().Order("created_at desc").Find(&posts)

    type PostView struct {
        Post
        TimeAgo string
    }
    var views []PostView
    for _, p := range posts {
        views = append(views, PostView{
            Post:    p,
            TimeAgo: timex.FromTime(p.CreatedAt).DiffForHumans(), // "2 hours ago"
        })
    }

    return c.View("posts/index", map[string]any{"posts": views})
}

Best Practices

  • Use StartOfDay() / EndOfDay() for date range queries — avoids off-by-one bugs
  • Use DiffForHumans() for UI display, DiffInDays() for business logic
  • Use IsBetween() for eligibility checks (promotions, trial windows, schedules)
  • Always use .Time() when passing into GORM queries to get back the raw time.Time
  • Use Parse() for user input — it auto-detects RFC3339, datetime, and date formats