How to Use the Golang Time Package? Code Examples Included

The Go time package offers accurate, timezone-aware, and thread-safe time handling using the Gregorian calendar with monotonic and wall clock support.

Go Time Package

The Go time package provides comprehensive functionality for measuring and displaying time. It follows a design philosophy that prioritizes accuracy, timezone awareness, and thread safety. The package uses a Gregorian calendar with no leap seconds and distinguishes between "wall clock" time (for telling time) and "monotonic clock" time (for measuring time intervals).

Key Design Principles

  • Immutability: time.Time values are immutable; operations return new instances
  • Thread Safety: All time operations are safe for concurrent use
  • Timezone Awareness: Every time.Time has an associated time.Location
  • Precision: Nanosecond precision for all time operations
  • Monotonic Clock Support: Robust time measurement unaffected by clock adjustments

Core Types

time.Time

Represents an instant in time with nanosecond precision. Contains both wall clock and optional monotonic clock readings.

type Time struct {
    // Internal fields are unexported
    // wall and ext encode the wall time and optional monotonic reading
}

Key characteristics:

  • Zero value: January 1, year 1, 00:00:00.000000000 UTC
  • Immutable: methods return new Time values
  • Thread-safe for concurrent reads
  • Contains both wall clock and optional monotonic clock readings

time.Duration

Represents elapsed time as an int64 nanosecond count, supporting approximately 290 years.

type Duration int64

// Predefined constants
const (
    Nanosecond  Duration = 1
    Microsecond          = 1000 * Nanosecond
    Millisecond          = 1000 * Microsecond
    Second               = 1000 * Millisecond
    Minute               = 60 * Second
    Hour                 = 60 * Minute
)

time.Location

Represents a time zone, mapping time instants to the zone in use at that time.

var (
    UTC   *Location = &utcLoc   // UTC timezone
    Local *Location = &localLoc // System's local timezone
)

Time Creation and Current Time

Learn how to get the current time and create specific timestamps using Go’s built-in functions. 

Getting Current Time

// Get current time with monotonic clock reading
now := time.Now()
fmt.Println(now) // 2025-08-27 14:55:00.123456789 +0700 +07 m=+0.000000001

// Get current time in specific timezone
loc, _ := time.LoadLocation("America/New_York")
nowNY := time.Now().In(loc)

Creating Specific Times

// Create specific time
t := time.Date(2025, time.August, 27, 14, 30, 0, 0, time.UTC)

// From Unix timestamp
unixTime := time.Unix(1693140600, 0) // seconds since epoch
unixMilli := time.UnixMilli(1693140600000) // milliseconds since epoch
unixMicro := time.UnixMicro(1693140600000000) // microseconds since epoch

Zero Time Detection

Detect and handle zero-value time.Time objects safely in your code.

var t time.Time
if t.IsZero() {
    fmt.Println("Time is zero value")
}

Golang Time Format and Parse

Go uses a unique reference time approach for formatting: Mon Jan 2 15:04:05 MST 2006 (which can be remembered as 01/02 03:04:05PM '06 -0700).

Predefined Layout Constants

const (
    Layout      = "01/02 03:04:05PM '06 -0700"
    ANSIC       = "Mon Jan _2 15:04:05 2006"
    UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
    RubyDate    = "Mon Jan 02 15:04:05 -0700 2006"
    RFC822      = "02 Jan 06 15:04 MST"
    RFC822Z     = "02 Jan 06 15:04 -0700"
    RFC850      = "Monday, 02-Jan-06 15:04:05 MST"
    RFC1123     = "Mon, 02 Jan 2006 15:04:05 MST"
    RFC1123Z    = "Mon, 02 Jan 2006 15:04:05 -0700"
    RFC3339     = "2006-01-02T15:04:05Z07:00"
    RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
    Kitchen     = "3:04PM"
    DateTime    = "2006-01-02 15:04:05"
    DateOnly    = "2006-01-02"
    TimeOnly    = "15:04:05"
)

Formatting Examples

now := time.Now()

// Using predefined constants
fmt.Println(now.Format(time.RFC3339))     // 2025-08-27T14:55:00Z
fmt.Println(now.Format(time.Kitchen))     // 2:55PM
fmt.Println(now.Format(time.DateOnly))    // 2025-08-27

// Custom formatting
fmt.Println(now.Format("2006-01-02 15:04:05")) // 2025-08-27 14:55:00
fmt.Println(now.Format("Jan 2, 2006"))         // Aug 27, 2025
fmt.Println(now.Format("Monday, January 2"))    // Tuesday, August 27

Parsing Examples

// Parse with predefined layout
t1, err := time.Parse(time.RFC3339, "2025-08-27T14:55:00Z")
if err != nil {
    log.Fatal(err)
}

// Parse with custom layout
t2, err := time.Parse("2006-01-02 15:04:05", "2025-08-27 14:55:00")
if err != nil {
    log.Fatal(err)
}

// Parse in specific location
loc, _ := time.LoadLocation("America/New_York")
t3, err := time.ParseInLocation("2006-01-02 15:04:05", "2025-08-27 14:55:00", loc)

Layout Reference Guide

Component

Options

Example

Year

"2006", "06"

2025, 25

Month

"Jan", "January", "01", "1"

Aug, August, 08, 8

Day

"2", "_2", "02"

27, 27, 27

Weekday

"Mon", "Monday"

Tue, Tuesday

Hour

"15", "3", "03"

14, 2, 02

Minute

"4", "04"

5, 05

Second

"5", "05"

0, 00

Timezone

"-0700", "MST", "Z07:00"

+0700, +07, +07:00

Golang Time Duration Operations

Creating Durations

// From constants
d1 := 5 * time.Second
d2 := 2 * time.Minute + 30 * time.Second
d3 := time.Hour + 15 * time.Minute

// From string parsing
d4, err := time.ParseDuration("1h30m45s")
d5, err := time.ParseDuration("100ms")
d6, err := time.ParseDuration("2.5h")

Duration Methods

d := 90 * time.Minute

// Convert to different units
fmt.Println(d.Hours())        // 1.5
fmt.Println(d.Minutes())      // 90
fmt.Println(d.Seconds())      // 5400
fmt.Println(d.Milliseconds()) // 5400000
fmt.Println(d.Microseconds()) // 5400000000
fmt.Println(d.Nanoseconds())  // 5400000000000

// String representation
fmt.Println(d.String()) // 1h30m0s

// Absolute value
neg := -5 * time.Second
fmt.Println(neg.Abs()) // 5s

// Rounding and truncation
d := 1*time.Hour + 15*time.Minute + 30*time.Second + 918*time.Millisecond
fmt.Println(d.Round(time.Minute))    // 1h16m0s
fmt.Println(d.Truncate(time.Minute)) // 1h15m0s

Time Zone Handling

Loading Time Zones

// Load specific timezone
ny, err := time.LoadLocation("America/New_York")
if err != nil {
    log.Fatal(err)
}

// Load UTC and Local
utc := time.UTC
local := time.Local

// Create fixed timezone
// FixedZone(name, offset_in_seconds)
customTZ := time.FixedZone("GMT+8", 8*60*60)

Converting Between Time Zones

// Create time in UTC
utcTime := time.Date(2025, 8, 27, 14, 30, 0, 0, time.UTC)

// Convert to different timezones
ny, _ := time.LoadLocation("America/New_York")
tokyo, _ := time.LoadLocation("Asia/Tokyo")

nyTime := utcTime.In(ny)
tokyoTime := utcTime.In(tokyo)

fmt.Println("UTC:   ", utcTime.Format(time.RFC3339))
fmt.Println("NY:    ", nyTime.Format(time.RFC3339))
fmt.Println("Tokyo: ", tokyoTime.Format(time.RFC3339))

Working with DST

// Check if time is in DST
ny, _ := time.LoadLocation("America/New_York")
summer := time.Date(2025, 7, 15, 12, 0, 0, 0, ny)
winter := time.Date(2025, 12, 15, 12, 0, 0, 0, ny)

fmt.Println("Summer DST:", summer.IsDST()) // true
fmt.Println("Winter DST:", winter.IsDST()) // false

// Get timezone information
name, offset := summer.Zone()
fmt.Printf("Zone: %s, Offset: %d seconds\\n", name, offset)

Time Comparison and Arithmetic

Compare two times or calculate differences using Go’s intuitive API.

Time Comparison

t1 := time.Date(2025, 8, 27, 10, 0, 0, 0, time.UTC)
t2 := time.Date(2025, 8, 27, 11, 0, 0, 0, time.UTC)

// Comparison methods
fmt.Println(t1.Before(t2))  // true
fmt.Println(t1.After(t2))   // false
fmt.Println(t1.Equal(t2))   // false

// Compare method (Go 1.20+)
fmt.Println(t1.Compare(t2)) // -1 (t1 < t2)
fmt.Println(t2.Compare(t1)) // 1  (t2 > t1)
fmt.Println(t1.Compare(t1)) // 0  (t1 == t1)

// Prefer Equal() over == for reliable comparison
fmt.Println(t1 == t2)    // may be unreliable due to monotonic clock
fmt.Println(t1.Equal(t2)) // reliable comparison

Time Arithmetic

now := time.Now()

// Add duration
future := now.Add(2 * time.Hour)
past := now.Add(-30 * time.Minute)

// Add date components
nextYear := now.AddDate(1, 0, 0)    // +1 year
nextMonth := now.AddDate(0, 1, 0)   // +1 month
tomorrow := now.AddDate(0, 0, 1)    // +1 day

// Subtract times to get duration
elapsed := future.Sub(now)
fmt.Println(elapsed) // 2h0m0s

// Helper functions
since := time.Since(now)  // time.Now().Sub(now)
until := time.Until(future) // future.Sub(time.Now())

Rounding and Truncation

now := time.Now()

// Round to nearest hour
rounded := now.Round(time.Hour)

// Truncate to start of hour
truncated := now.Truncate(time.Hour)

// Strip monotonic clock reading
stripped := now.Round(0)

Monotonic Clock

The monotonic clock provides accurate time measurement unaffected by system clock adjustments.

Understanding Monotonic Clock

// Times from Now() include monotonic reading
start := time.Now()
time.Sleep(100 * time.Millisecond)
end := time.Now()

// Duration calculation uses monotonic clock if available
elapsed := end.Sub(start) // Accurate even if system clock changes

// Monotonic clock visible in String() output
fmt.Println(start) // includes "m=+0.000000001"

Operations That Strip Monotonic Clock

now := time.Now() // Has monotonic reading

// These operations strip monotonic reading:
utc := now.UTC()              // Timezone conversion
local := now.Local()          // Timezone conversion
ny := now.In(nyLocation)      // Timezone conversion
rounded := now.Round(time.Hour)    // Rounding (when d > 0)
truncated := now.Truncate(time.Hour) // Truncation (when d > 0)
dated := now.AddDate(0, 0, 1) // Date arithmetic

// Explicitly strip monotonic reading
stripped := now.Round(0)

Monotonic Clock Best Practices

  • Use for measuring elapsed time: elapsed := time.Since(start)
  • Don't rely on monotonic clock for serialization
  • Use t.Equal(u) instead of t == u for comparisons
  • Strip monotonic reading when using as map keys: t.Round(0)

Timers and Tickers

Timers

// Simple timer for one-time events
timer := time.NewTimer(5 * time.Second)
<-timer.C // Wait for timer to fire
fmt.Println("Timer fired!")

// Using After for simple delays
select {
case <-time.After(5 * time.Second):
    fmt.Println("Timeout!")
case data := <-dataChannel:
    fmt.Println("Received:", data)
}

// Timer with function callback
timer := time.AfterFunc(5*time.Second, func() {
    fmt.Println("Timer callback executed!")
})

// Stop timer if needed
if !timer.Stop() {
    // Timer already fired or was stopped
}

// Reset timer
timer.Reset(10 * time.Second)

Tickers

// Create ticker for repeated events
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop() // Always stop tickers to prevent leaks

for i := 0; i < 5; i++ {
    select {
    case t := <-ticker.C:
        fmt.Printf("Tick at %v\\n", t)
    }
}

// Using Tick for simple repeating events
c := time.Tick(1 * time.Second) // Returns nil if d <= 0
for t := range c {
    fmt.Printf("Tick: %v\\n", t)
    // Note: This creates an unstoppable ticker
}

// Reset ticker period
ticker.Reset(2 * time.Second)

Timer Safety and Performance

// Safe timer pattern
func safeTimerPattern() {
    timer := time.NewTimer(5 * time.Second)
    defer func() {
        if !timer.Stop() {
            // Drain channel if timer fired
            select {
            case <-timer.C:
            default:
            }
        }
    }()

    select {
    case <-timer.C:
        fmt.Println("Timer fired")
    case <-someOtherChannel():
        fmt.Println("Other event occurred")
        return
    }
}

>> Read more: A Comprehensive Guide to Concurrency in Golang

Performance Considerations

Timer Resolution

  • Unix systems: ~1ms resolution
  • Windows 1803+: ~0.5ms resolution
  • Older Windows: ~16ms resolution (can be improved with TimeBeginPeriod)

Memory and GC

// As of Go 1.23, timers and tickers are automatically GC'd
// No need to explicitly stop them for GC purposes

// However, still stop for logic purposes
ticker := time.NewTicker(time.Second)
defer ticker.Stop() // Good practice for clarity

// Avoid creating many short-lived timers in hot paths
// Consider using a single timer pool or time wheel

Benchmark Example

func BenchmarkTimeOperations(b *testing.B) {
    now := time.Now()

    b.Run("Now", func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            _ = time.Now()
        }
    })

    b.Run("Format", func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            _ = now.Format(time.RFC3339)
        }
    })

    b.Run("Parse", func(b *testing.B) {
        timeStr := "2025-08-27T14:55:00Z"
        for i := 0; i < b.N; i++ {
            _, _ = time.Parse(time.RFC3339, timeStr)
        }
    })
}

Best Practices

Always Handle Parsing Errors

// Bad
t, _ := time.Parse(time.RFC3339, userInput)

// Good
t, err := time.Parse(time.RFC3339, userInput)
if err != nil {
    return fmt.Errorf("invalid time format: %w", err)
}

Use Appropriate Layout Constants

// Bad - magic strings
t.Format("2006-01-02T15:04:05Z07:00")

// Good - use constants
t.Format(time.RFC3339)

// Good - define custom constants
const CustomLayout = "2006-01-02 15:04:05"
t.Format(CustomLayout)

Be Explicit About Time Zones

// Bad - ambiguous timezone
t, _ := time.Parse("2006-01-02 15:04:05", "2025-08-27 14:55:00")

// Good - explicit timezone
loc, _ := time.LoadLocation("America/New_York")
t, _ := time.ParseInLocation("2006-01-02 15:04:05", "2025-08-27 14:55:00", loc)

// Or use timezone-aware format
t, _ := time.Parse(time.RFC3339, "2025-08-27T14:55:00Z")

Use time.Equal() for Comparisons

// Bad - may fail due to monotonic clock differences
if t1 == t2 {
    // ...
}

// Good - handles monotonic clock properly
if t1.Equal(t2) {
    // ...
}

Measure Elapsed Time Correctly

// Good - uses monotonic clock
start := time.Now()
doWork()
elapsed := time.Since(start)

// Also good
start := time.Now()
doWork()
elapsed := time.Now().Sub(start)

Store UTC in Databases

// Good practice - store UTC, display in local timezone
func storeTime(t time.Time) {
    utcTime := t.UTC()
    // Store utcTime in database
}

func displayTime(utcTime time.Time, userTZ string) string {
    loc, _ := time.LoadLocation(userTZ)
    localTime := utcTime.In(loc)
    return localTime.Format("2006-01-02 15:04:05 MST")
}

Handle Zero Times

func processTime(t time.Time) error {
    if t.IsZero() {
        return errors.New("time cannot be zero")
    }
    // Process non-zero time
    return nil
}

Use Context for Timeouts

func processWithTimeout(ctx context.Context) error {
    ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
    defer cancel()

    // Use ctx for operations that should respect timeout
    return doWorkWithContext(ctx)
}

Common Pitfalls and Solutions

Layout String Confusion

// Common mistake - using wrong reference time
t.Format("YYYY-MM-DD") // Wrong! Go doesn't use these placeholders

// Correct - use Go's reference time
t.Format("2006-01-02") // Correct

Time Zone Loading Errors

// Bad - ignoring errors
loc, _ := time.LoadLocation("Invalid/Timezone")

// Good - handle errors
loc, err := time.LoadLocation("America/New_York")
if err != nil {
    log.Printf("Failed to load timezone: %v", err)
    loc = time.UTC // fallback to UTC
}

Timer/Ticker Resource Leaks

// Bad - potential resource leak
func badTicker() {
    ticker := time.NewTicker(time.Second)
    for range ticker.C {
        // Process tick
        if someCondition {
            return // Ticker never stopped!
        }
    }
}

// Good - always stop tickers
func goodTicker() {
    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            // Process tick
            if someCondition {
                return
            }
        }
    }
}

Monotonic Clock Stripping

// Problem - using time as map key
times := make(map[time.Time]string)
t1 := time.Now()
t2 := time.Date(2025, 8, 27, 14, 55, 0, 0, time.UTC)
// t1 and t2 might represent same time but have different monotonic readings

// Solution - strip monotonic reading
times[t1.Round(0)] = "value1"
times[t2.Round(0)] = "value2"

Parsing Ambiguous Formats

// Problem - ambiguous date format
dateStr := "01/02/2006" // Is this Jan 2 or Feb 1?

// Solution - use unambiguous formats
// Use ISO 8601 format
dateStr := "2006-01-02"
t, err := time.Parse("2006-01-02", dateStr)

// Or be explicit about format
t, err := time.Parse("01/02/2006", "01/02/2006") // MM/DD/YYYY
t, err := time.Parse("02/01/2006", "01/02/2006") // DD/MM/YYYY

Examples and Use Cases

API Rate Limiting

type RateLimiter struct {
    tokens    int
    maxTokens int
    interval  time.Duration
    lastRefill time.Time
    mu        sync.Mutex
}

func NewRateLimiter(maxTokens int, interval time.Duration) *RateLimiter {
    return &RateLimiter{
        tokens:     maxTokens,
        maxTokens:  maxTokens,
        interval:   interval,
        lastRefill: time.Now(),
    }
}

func (rl *RateLimiter) Allow() bool {
    rl.mu.Lock()
    defer rl.mu.Unlock()

    now := time.Now()
    elapsed := now.Sub(rl.lastRefill)

    if elapsed >= rl.interval {
        rl.tokens = rl.maxTokens
        rl.lastRefill = now
    }

    if rl.tokens > 0 {
        rl.tokens--
        return true
    }

    return false
}

Retry with Exponential Backoff

func retryWithBackoff(operation func() error, maxRetries int) error {
    baseDelay := 100 * time.Millisecond
    maxDelay := 10 * time.Second

    for attempt := 0; attempt < maxRetries; attempt++ {
        if err := operation(); err == nil {
            return nil
        }

        if attempt == maxRetries-1 {
            return fmt.Errorf("operation failed after %d attempts", maxRetries)
        }

        // Calculate delay with exponential backoff
        delay := time.Duration(float64(baseDelay) * math.Pow(2, float64(attempt)))
        if delay > maxDelay {
            delay = maxDelay
        }

        time.Sleep(delay)
    }

    return nil
}

Scheduled Task Runner

type Scheduler struct {
    tasks map[string]*ScheduledTask
    mu    sync.RWMutex
    stop  chan struct{}
}

type ScheduledTask struct {
    Name     string
    Interval time.Duration
    Fn       func()
    ticker   *time.Ticker
}

func NewScheduler() *Scheduler {
    return &Scheduler{
        tasks: make(map[string]*ScheduledTask),
        stop:  make(chan struct{}),
    }
}

func (s *Scheduler) AddTask(name string, interval time.Duration, fn func()) {
    s.mu.Lock()
    defer s.mu.Unlock()

    task := &ScheduledTask{
        Name:     name,
        Interval: interval,
        Fn:       fn,
        ticker:   time.NewTicker(interval),
    }

    s.tasks[name] = task

    go func() {
        for {
            select {
            case <-task.ticker.C:
                fn()
            case <-s.stop:
                return
            }
        }
    }()
}

func (s *Scheduler) Stop() {
    s.mu.Lock()
    defer s.mu.Unlock()

    close(s.stop)

    for _, task := range s.tasks {
        task.ticker.Stop()
    }
}

Time-based Cache with TTL

type TTLCache struct {
    items map[string]*cacheItem
    mu    sync.RWMutex
}

type cacheItem struct {
    value     interface{}
    expiresAt time.Time
}

func NewTTLCache() *TTLCache {
    cache := &TTLCache{
        items: make(map[string]*cacheItem),
    }

    // Start cleanup goroutine
    go cache.cleanup()

    return cache
}

func (c *TTLCache) Set(key string, value interface{}, ttl time.Duration) {
    c.mu.Lock()
    defer c.mu.Unlock()

    c.items[key] = &cacheItem{
        value:     value,
        expiresAt: time.Now().Add(ttl),
    }
}

func (c *TTLCache) Get(key string) (interface{}, bool) {
    c.mu.RLock()
    defer c.mu.RUnlock()

    item, exists := c.items[key]
    if !exists {
        return nil, false
    }

    if time.Now().After(item.expiresAt) {
        return nil, false
    }

    return item.value, true
}

func (c *TTLCache) cleanup() {
    ticker := time.NewTicker(1 * time.Minute)
    defer ticker.Stop()

    for range ticker.C {
        c.mu.Lock()
        now := time.Now()
        for key, item := range c.items {
            if now.After(item.expiresAt) {
                delete(c.items, key)
            }
        }
        c.mu.Unlock()
    }
}

Business Hours Checker

type BusinessHours struct {
    timezone     *time.Location
    openTime     time.Duration  // Duration since midnight
    closeTime    time.Duration  // Duration since midnight
    workdays     []time.Weekday
    holidays     []time.Time
}

func NewBusinessHours(timezone string) (*BusinessHours, error) {
    loc, err := time.LoadLocation(timezone)
    if err != nil {
        return nil, err
    }

    return &BusinessHours{
        timezone:  loc,
        openTime:  9 * time.Hour,  // 9 AM
        closeTime: 17 * time.Hour, // 5 PM
        workdays: []time.Weekday{
            time.Monday, time.Tuesday, time.Wednesday,
            time.Thursday, time.Friday,
        },
        holidays: []time.Time{},
    }, nil
}

func (bh *BusinessHours) IsBusinessTime(t time.Time) bool {
    // Convert to business timezone
    localTime := t.In(bh.timezone)

    // Check if it's a workday
    isWorkday := false
    for _, day := range bh.workdays {
        if localTime.Weekday() == day {
            isWorkday = true
            break
        }
    }

    if !isWorkday {
        return false
    }

    // Check if it's a holiday
    for _, holiday := range bh.holidays {
        if isSameDate(localTime, holiday.In(bh.timezone)) {
            return false
        }
    }

    // Check business hours
    todayStart := time.Date(localTime.Year(), localTime.Month(), localTime.Day(),
        0, 0, 0, 0, bh.timezone)

    openTime := todayStart.Add(bh.openTime)
    closeTime := todayStart.Add(bh.closeTime)

    return localTime.After(openTime) && localTime.Before(closeTime)
}

func isSameDate(t1, t2 time.Time) bool {
    y1, m1, d1 := t1.Date()
    y2, m2, d2 := t2.Date()
    return y1 == y2 && m1 == m2 && d1 == d2
}

Performance Measurement

type PerformanceTracker struct {
    measurements map[string][]time.Duration
    mu          sync.Mutex
}

func NewPerformanceTracker() *PerformanceTracker {
    return &PerformanceTracker{
        measurements: make(map[string][]time.Duration),
    }
}

func (pt *PerformanceTracker) Track(name string, fn func()) {
    start := time.Now()
    fn()
    elapsed := time.Since(start)

    pt.mu.Lock()
    pt.measurements[name] = append(pt.measurements[name], elapsed)
    pt.mu.Unlock()
}

func (pt *PerformanceTracker) Stats(name string) (avg, min, max time.Duration, count int) {
    pt.mu.Lock()
    durations := pt.measurements[name]
    pt.mu.Unlock()

    if len(durations) == 0 {
        return 0, 0, 0, 0
    }

    var total time.Duration
    min = durations[0]
    max = durations[0]

    for _, d := range durations {
        total += d
        if d < min {
            min = d
        }
        if d > max {
            max = d
        }
    }

    avg = total / time.Duration(len(durations))
    count = len(durations)
    return
}

Conclusion

This comprehensive guide covers all essential aspects of Go's time package, from basic usage to advanced patterns and best practices. The examples demonstrate real-world applications and help avoid common pitfalls when working with time in Go applications.

>>> Follow and Contact Relia Software for more information!

  • golang
  • coding