timestamp

package
v1.0.0-alpha.40 Latest Latest
Warning

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

Go to latest
Published: Mar 13, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package timestamp provides standardized Unix timestamp handling utilities.

Overview

The timestamp package establishes int64 milliseconds as the canonical timestamp format throughout the codebase. This eliminates common timestamp parsing bugs and provides consistent behavior across all components.

Design decisions:

  • All timestamps are Unix milliseconds (ms since epoch, UTC)
  • Zero value (0) means "not set" or "unknown"
  • Functions handle zero values gracefully
  • Automatic detection of seconds vs milliseconds input

Why Milliseconds?

Milliseconds provide sufficient precision for most applications while avoiding the complexity of nanoseconds. They map naturally to JavaScript Date.now() and most database timestamp columns.

Zero Value Semantics

A timestamp of 0 is treated as "unset":

timestamp.Format(0)      // Returns ""
timestamp.FromUnixMs(0)  // Returns time.Time{} (zero time)
timestamp.Since(0)       // Returns 0
timestamp.Min(0, ts)     // Returns ts (0 treated as "later")

This allows timestamp fields to be optional without using pointers.

Usage

Getting current time:

now := timestamp.Now()  // Returns current Unix milliseconds

Converting between types:

// time.Time → int64
ts := timestamp.ToUnixMs(time.Now())

// int64 → time.Time
t := timestamp.FromUnixMs(ts)
t := timestamp.ToTime(ts)  // Alias for readability

Formatting for display:

s := timestamp.Format(ts)  // Returns "2024-01-15T10:30:00Z"

Parsing various inputs:

// RFC3339 string
ts := timestamp.Parse("2024-01-15T10:30:00Z")

// Unix seconds (auto-detected)
ts := timestamp.Parse(1705315800)

// Unix milliseconds (auto-detected)
ts := timestamp.Parse(1705315800000)

// time.Time
ts := timestamp.Parse(time.Now())

Time arithmetic:

// Add duration
future := timestamp.Add(ts, 1*time.Hour)

// Subtract duration
past := timestamp.Sub(ts, 30*time.Minute)

// Duration between timestamps
elapsed := timestamp.Between(start, end)

// Duration since timestamp
age := timestamp.Since(ts)

Comparison:

earlier := timestamp.Min(ts1, ts2)
later := timestamp.Max(ts1, ts2)
timestamp.IsZero(ts)  // true if 0

Validation:

if err := timestamp.Validate(ts); err != nil {
    // Invalid: negative or unreasonably far in future
}

Migration Guide

Replace common patterns:

// Old: time.Now().Unix()
// New:
now := timestamp.Now()

// Old: time.Unix(sec, 0)
// New:
t := timestamp.FromUnixMs(sec * 1000)

// Old: time.Parse(time.RFC3339, s)
// New:
ts := timestamp.Parse(s)

// Old: t.Format(time.RFC3339)
// New:
s := timestamp.Format(ts)

Auto-Detection Logic

Parse() automatically detects seconds vs milliseconds:

  • Values > 1e12 (year ~2001 in ms) are treated as milliseconds
  • Values ≤ 1e12 are treated as seconds and converted

This handles both JavaScript (milliseconds) and Unix (seconds) conventions.

Thread Safety

All functions are pure (no shared state) and safe for concurrent use.

See Also

Related packages:

Package timestamp provides standardized Unix timestamp handling utilities.

This package uses int64 milliseconds as the canonical timestamp format to eliminate timestamp parsing bugs and provide consistent behavior across the codebase. All timestamps are stored as milliseconds since Unix epoch (UTC).

Zero Value Semantics:

  • A timestamp value of 0 means "not set" or "unknown"
  • Functions handle zero values gracefully, returning appropriate defaults

Migration Guide:

  • Replace time.Now().Unix() with timestamp.Now()
  • Replace time.Unix(sec, 0) with timestamp.FromUnixMs(sec * 1000)
  • Replace RFC3339 string parsing with timestamp.Parse()

Usage Examples:

// Current time
now := timestamp.Now()

// Convert from time.Time
t := time.Now()
ts := timestamp.ToUnixMs(t)

// Convert to time.Time
t := timestamp.FromUnixMs(ts)

// Format for display
display := timestamp.Format(ts)

// Parse various formats
ts := timestamp.Parse("2023-01-01T12:00:00Z")
ts := timestamp.Parse(1672574400000)

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Add

func Add(ms int64, d time.Duration) int64

Add adds a duration to a timestamp and returns the new timestamp. Returns 0 if the input timestamp is zero.

Example

ExampleAdd demonstrates timestamp arithmetic

package main

import (
	"fmt"
	"time"

	"github.com/c360studio/semstreams/pkg/timestamp"
)

func main() {
	ts := int64(1673785845123)

	// Add 1 hour
	future := timestamp.Add(ts, time.Hour)
	fmt.Printf("Original: %s\n", timestamp.Format(ts))
	fmt.Printf("Plus 1 hour: %s\n", timestamp.Format(future))

	// Add to zero timestamp returns zero
	zero := timestamp.Add(0, time.Hour)
	fmt.Printf("Add to zero: %d\n", zero)

}
Output:

Original: 2023-01-15T12:30:45Z
Plus 1 hour: 2023-01-15T13:30:45Z
Add to zero: 0

func Between

func Between(start, end int64) time.Duration

Between returns the duration between two timestamps. Returns 0 if either timestamp is zero.

Example

ExampleBetween demonstrates calculating duration between timestamps

package main

import (
	"fmt"
	"time"

	"github.com/c360studio/semstreams/pkg/timestamp"
)

func main() {
	start := int64(1673785845123)
	end := timestamp.Add(start, 30*time.Minute)

	duration := timestamp.Between(start, end)
	fmt.Printf("Duration: %v\n", duration)

	// Zero timestamps return zero duration
	zeroDuration := timestamp.Between(0, end)
	fmt.Printf("With zero: %v\n", zeroDuration)

}
Output:

Duration: 30m0s
With zero: 0s

func Format

func Format(ms int64) string

Format converts Unix milliseconds to RFC3339 string for display. Returns empty string if timestamp is 0.

Example

ExampleFormat demonstrates formatting timestamps for display

package main

import (
	"fmt"

	"github.com/c360studio/semstreams/pkg/timestamp"
)

func main() {
	ts := int64(1673785845123)
	formatted := timestamp.Format(ts)
	fmt.Printf("Formatted: %s\n", formatted)

	// Zero timestamp returns empty string
	empty := timestamp.Format(0)
	fmt.Printf("Zero formatted: '%s'\n", empty)

}
Output:

Formatted: 2023-01-15T12:30:45Z
Zero formatted: ''

func FromUnixMs

func FromUnixMs(ms int64) time.Time

FromUnixMs converts Unix milliseconds to time.Time. Returns zero time if timestamp is 0.

Example

ExampleFromUnixMs demonstrates converting milliseconds to time.Time

package main

import (
	"fmt"
	"time"

	"github.com/c360studio/semstreams/pkg/timestamp"
)

func main() {
	ts := int64(1673785845123)
	t := timestamp.FromUnixMs(ts)
	fmt.Printf("Milliseconds to time.Time: %s\n", t.UTC().Format(time.RFC3339))

	// Zero timestamp returns zero time
	zeroTime := timestamp.FromUnixMs(0)
	fmt.Printf("Zero timestamp: %v\n", zeroTime.IsZero())

}
Output:

Milliseconds to time.Time: 2023-01-15T12:30:45Z
Zero timestamp: true

func IsZero

func IsZero(ms int64) bool

IsZero checks if a timestamp is unset (zero).

func Max

func Max(a, b int64) int64

Max returns the later of two timestamps. Zero values are treated as "earlier than any other time".

func Min

func Min(a, b int64) int64

Min returns the earlier of two timestamps. Zero values are treated as "later than any other time".

func Now

func Now() int64

Now returns the current time as Unix milliseconds.

Example

ExampleNow demonstrates getting the current timestamp

package main

import (
	"fmt"

	"github.com/c360studio/semstreams/pkg/timestamp"
)

func main() {
	ts := timestamp.Now()
	fmt.Printf("Current timestamp: %d (milliseconds)\n", ts)
	// Output would vary, so we'll just show the format
}

func Parse

func Parse(input any) int64

Parse converts various timestamp formats to Unix milliseconds. Supports:

  • int64 (assumed to be milliseconds if > 1e12, otherwise seconds)
  • float64 (converted to int64, same logic as int64)
  • string (RFC3339 or Unix timestamp string)
  • time.Time
  • nil/zero values (returns 0)

Returns 0 for invalid input or parsing errors.

Example

ExampleParse demonstrates parsing various timestamp formats

package main

import (
	"fmt"

	"github.com/c360studio/semstreams/pkg/timestamp"
)

func main() {
	// Parse RFC3339 string
	ts1 := timestamp.Parse("2023-01-15T12:30:45Z")
	fmt.Printf("RFC3339 parsed: %d\n", ts1)

	// Parse Unix seconds
	ts2 := timestamp.Parse(int64(1673784645))
	fmt.Printf("Unix seconds parsed: %d\n", ts2)

	// Parse Unix milliseconds
	ts3 := timestamp.Parse(int64(1673784645123))
	fmt.Printf("Unix milliseconds parsed: %d\n", ts3)

}
Output:

RFC3339 parsed: 1673785845000
Unix seconds parsed: 1673784645000
Unix milliseconds parsed: 1673784645123

func Since

func Since(ms int64) time.Duration

Since returns the duration since the given timestamp. Returns 0 if timestamp is zero.

func Sub

func Sub(ms int64, d time.Duration) int64

Sub subtracts a duration from a timestamp and returns the new timestamp. Returns 0 if the input timestamp is zero.

func ToTime

func ToTime(ms int64) time.Time

ToTime is an alias for FromUnixMs for better readability.

func ToUnixMs

func ToUnixMs(t time.Time) int64

ToUnixMs converts a time.Time to Unix milliseconds.

Example

ExampleToUnixMs demonstrates converting time.Time to milliseconds

package main

import (
	"fmt"
	"time"

	"github.com/c360studio/semstreams/pkg/timestamp"
)

func main() {
	t := time.Date(2023, 1, 15, 12, 30, 45, 123000000, time.UTC)
	ts := timestamp.ToUnixMs(t)
	fmt.Printf("time.Time to milliseconds: %d\n", ts)

}
Output:

time.Time to milliseconds: 1673785845123

func Validate

func Validate(ms int64) error

Validate checks if a timestamp is valid (non-negative and reasonable). Returns an error if the timestamp is negative or unreasonably large.

Types

This section is empty.

Jump to

Keyboard shortcuts

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