years

package module
v0.0.7 Latest Latest
Warning

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

Go to latest
Published: Dec 23, 2025 License: MIT Imports: 13 Imported by: 0

README

years: Powerful Time-Based Navigation in Go

Years Logo

License

years is a Golang library designed for time-based sorting and iterating over things.
years allows you to build powerful tools for navigating through time-based data structures (calendars files, logs etc).
Also it's yet another time parser for Go as well.

Features

  • Calendar Navigation: Provides easy navigation through calendar-like structures, allowing for relative and absolute time-based navigation.
  • Flexible Time Representation: Supports simple date strings, Unix timestamps, and files (flat or nested structures).
  • File-Based Time Retrieval: Handles time based on file metadata (modification/creation/access time) or file names.
  • Time Parsing and Manipulation: Offers powerful time parsing capabilities and time mutation functions.

Installation

To install the years library, use the following go get command:

go get github.com/amberpixels/years

Usage

Basic Example

Here's a simple example demonstrating how to use years with strings representing dates:

dates := []string{"2020, Dec 1", "2020, Dec 2", "2020, Dec 3"}
layout := "2006, Jan 2" // Go-formatted time layout

v := years.NewVoyager(years.WaypointGroupFromStrings(dates), layout)

// iterates through all dates in the Future->Past direction
// Here w.Identifier() returns the string value itself
v.Traverse(func (w Waypoint) { fmt.Println(w.Identifier()) }, years.O_PAST())

// Dates are not required to be same layout:
dates2 := []string{"2020-01-01", "2020-01", "2020-Jan-03"}
years.ExtendParserDefaults(years.WithLayouts("2006-01-02", "2006-01-02", "2006-Jan-02"))
v2 := years.NewVoyager(years.WaypointGroupFromStrings(dates2)) // not specifying layouts, so default are used
v2.Traverse(func (w Waypoint) { fmt.Println(w.Identifier()) }, years.O_PAST())

Advanced Example with Files

The following example shows how to work with a nested file structure representing calendar dates:

// Declaring path to a calendar directory
var CalendarPath = "path/to/calendar"
const layout = "2006/Jan/2006-01-02.txt" // using Golang time package layout

wf, err := years.NewTimeNamedWaypointFile(CalendarPath, layout)
if err != nil {
    panic(err)
}

v = years.NewVoyager(wf)
// iterates through all finite files (excluding directories) in Past->Future direction
v.Traverse(func (w Waypoint) {
    fmt.Println(w.Path())
}, years.O_FUTURE(), years.O_LEAVES_ONLY())

// Quick navigation through the calendar
yesterday, err := v.Navigate("yesterday")
if err != nil {
    panic(err)
}
fmt.Println("Yesterday's file:", w.Path())

Time Parsing and Manipulation

years can also be used as a time-handling library. It provides various time parsing and mutation functions:

Parsing time
// 1. Simplest case: parses time almost the same way as Go's time.Parse
t, err := years.Parse("2006-01-02", "2024-05-26")
if err != nil {
    panic(err)
}
fmt.Println("Parsed time:", t)

// Note: Difference is in the fact that it supports layouts with timestamp parts:
// e.g. `U@` for second timestamps, `U@000` for millisecond timestamps, etc
t, err = years.Parse("[email protected]", "logs-1717852417000.log")
if err != nil {
    panic(err)
}
fmt.Println("Parsed time:", t)

// 2. Advanced parsing:
p := NewParser(
    AcceptUnixSeconds(),
    AcceptAliases(),
    WithLayouts(
        "2006",
        "2006-01", "2006-Jan",
        "2006-Jan-02", "2006-01-02",
    ),
)

t, _ = p.Parse("", "2020-01") // not specifying layouts will use all parser's accepted layouts
t, _ = p.JustParse("2020-01") // syntax sugar

// aliases:
t, _ = p.JustParse("today")
t, _ = p.JustParse("next-week")
// etc

// 3. Configuring global parser:
years.SetParserDefaults(
    AcceptUnixSeconds(),
    AcceptAliases(),
)

t, _ = years.JustParse("1717852417")

Mutating time
t, _ := time.Parse("now")
mutatedTime := years.Mutate(&t).TruncateToDay().Time()
fmt.Println("Mutated time:", mutatedTime)

Contributing

years welcomes contributions! Feel free to open issues, suggest improvements, or submit pull requests. Contribution guidelines for this project

License

This project is licensed under the MIT License.

Contact

For any questions or issues, feel free to open an issue on the GitHub repository or contact the maintainer at [email protected]

Documentation

Index

Constants

View Source
const (
	LayoutTimestampSeconds      = "U@"
	LayoutTimestampMilliseconds = "U@000"
	LayoutTimestampMicroseconds = "U@000000"
	LayoutTimestampNanoseconds  = "U@000000000"
)

Variables

View Source
var DateUnitsDict = struct {
	Day   DateUnit
	Month DateUnit
	Year  DateUnit

	UnixSecond      DateUnit
	UnixMillisecond DateUnit
	UnixMicrosecond DateUnit
	UnixNanosecond  DateUnit
}{
	Day:   Day,
	Month: Month,
	Year:  Year,

	UnixSecond:      UnixSecond,
	UnixMillisecond: UnixMillisecond,
	UnixMicrosecond: UnixMicrosecond,
	UnixNanosecond:  UnixNanosecond,
}

DateUnitsDict holds all available DateUnits.

View Source
var DefaultParser = func() *Parser {
	return NewParser(defaultParserOptions...)
}

DefaultParser makes a default parser

View Source
var LayoutFormatDict = struct {
	GoFormat      LayoutFormat
	UnixTimestamp LayoutFormat
}{
	GoFormat:      LayoutFormatGo,
	UnixTimestamp: LayoutFormatUnixTimestamp,
}

LayoutFormatDict holds all available LayoutFormats.

Functions

func ExtendParserDefaults

func ExtendParserDefaults(opts ...ParserOption)

func JustParse added in v0.0.2

func JustParse(value string) (time.Time, error)

JustParse calls JustParse of a default parser.

func JustParseRaw added in v0.0.5

func JustParseRaw(value any) (time.Time, error)

JustParseRaw attempts to convert or parse any value into a time.Time. - If value is time.Time (or custom type convertible to time.Time) the underlined time.Time is returned. - If value is a string or custom string type, passes to JustParse. - If value implements fmt.Stringer, uses its String() to be parsed via JustParse. - If value is a numeric type (int, uint, float), stringifies and passes to JustParse. - If value is nil, it returns a zero time.Time. Returns an error for unsupported types.

func Parse

func Parse(layout string, value string) (time.Time, error)

Parse calls Parse of a default parser.

func ResetParserDefaults

func ResetParserDefaults()

func SetParserDefaults

func SetParserDefaults(opts ...ParserOption)

func SetStdClock

func SetStdClock(c Clock)

SetStdClock sets the default clock to use. Note: this considered to be called from tests, so time.Now() is mockable.

Types

type Clock

type Clock interface {
	Now() time.Time
}

type DateUnit

type DateUnit int

DateUnit stays for the unit of a date like Day/Month/Year/etc.

const (
	UnitUndefined DateUnit = iota
	// Day as day of the month
	// TODO(nice-to-have) support day of the week + day of the year.
	Day  DateUnit = 1 << (iota - 1)
	Week          // not supported yet
	Month
	Quarter // not supported yet
	Year

	// UnixSecond as well as UnixMillisecond, UnixMicrosecond, UnixNanosecond
	// are special units for Unix timestamps.
	UnixSecond
	UnixMillisecond
	UnixMicrosecond
	UnixNanosecond
)

func (DateUnit) Defined

func (du DateUnit) Defined() bool

func (DateUnit) String

func (du DateUnit) String() string

type LayoutDetails

type LayoutDetails struct {
	// MinimalUnit e.g. Day for "2006-01-02" and Month for "2006-01"
	MinimalUnit DateUnit

	// Format is the format of the time used in the layout
	Format LayoutFormat

	// Units met in layout
	Units []DateUnit
}

LayoutDetails stores parsed meta information about given layout string. e.g. "2006-02-01".

func ParseLayout

func ParseLayout(layout string) *LayoutDetails

ParseLayout parses given layout string and returns LayoutDetails.

Note: it's a pretty hacky/weak function, but we're OK with it for now.

func (*LayoutDetails) HasUnit

func (lm *LayoutDetails) HasUnit(q DateUnit) bool

type LayoutFormat

type LayoutFormat int
const (
	LayoutFormatUndefined LayoutFormat = iota
	// LayoutFormatGo is a format that is supported by Go time.Parse.
	LayoutFormatGo LayoutFormat = 1 << (iota - 1)
	// LayoutFormatUnixTimestamp is a format that parses time from Unix timestamp (seconds or milliseconds).
	LayoutFormatUnixTimestamp
)

func (LayoutFormat) String

func (lf LayoutFormat) String() string

type MutatingTime

type MutatingTime struct {
	// contains filtered or unexported fields
}

MutatingTime is a wrapper around a time.Time pointer, providing fluent setter methods that mutate the underlying time.

Example:

t, _ := time.Parse("2006-01-02 15:04:05", "2025-04-30 13:45:00")
Mutate(&t).SetMonth(time.April).SetYear(2021)
// t is now 2021-04-30 13:45:00.

Use Mutate to obtain a MutatingTime for in-place modifications.

func Mutate

func Mutate(v *time.Time) *MutatingTime

Mutate returns a MutatingTime for the given *time.Time.

func (*MutatingTime) SetDay

func (mt *MutatingTime) SetDay(day int) *MutatingTime

SetDay sets the day of the month to the provided value.

func (*MutatingTime) SetHour

func (mt *MutatingTime) SetHour(hour int) *MutatingTime

SetHour sets the hour (0–23). Panics if out of range.

func (*MutatingTime) SetMillisecond added in v0.0.5

func (mt *MutatingTime) SetMillisecond(ms int) *MutatingTime

SetMillisecond sets the millisecond (0–999) by overriding the nanosecond field. Panics if out of range.

func (*MutatingTime) SetMinute

func (mt *MutatingTime) SetMinute(minute int) *MutatingTime

SetMinute sets the minute (0–59). Panics if out of range.

func (*MutatingTime) SetMonth

func (mt *MutatingTime) SetMonth(month time.Month) *MutatingTime

SetMonth sets the month to the provided value.

func (*MutatingTime) SetNanosecond

func (mt *MutatingTime) SetNanosecond(nano int) *MutatingTime

SetNanosecond sets the nanosecond (0–999,999,999). Panics if out of range.

func (*MutatingTime) SetSecond

func (mt *MutatingTime) SetSecond(second int) *MutatingTime

SetSecond sets the second (0–59). Panics if out of range.

func (*MutatingTime) SetYear

func (mt *MutatingTime) SetYear(year int) *MutatingTime

SetYear sets the year to the provided value.

func (*MutatingTime) Time

func (mt *MutatingTime) Time() time.Time

Time returns the underlying time.Time value.

func (*MutatingTime) TruncateToDay

func (mt *MutatingTime) TruncateToDay() *MutatingTime

TruncateToDay sets the hour, minute, second, and nanosecond to zero.

type Parser

type Parser struct {
	// contains filtered or unexported fields
}

func NewParser

func NewParser(options ...ParserOption) *Parser

func (*Parser) JustParse

func (p *Parser) JustParse(value string) (time.Time, error)

JustParse is a shortcut for Parse("", value) (so using all parser's accepted layouts).

func (*Parser) Parse

func (p *Parser) Parse(layout string, value string) (time.Time, error)

Parse parses time from given value using given layout (or using all parser's accepted layouts if layout is empty).

func (*Parser) ParseEpoch added in v0.0.3

func (p *Parser) ParseEpoch(v int64) (time.Time, bool, error)

ParseEpoch converts the given epoch timestamp int64 as a time.Time, considering input as seconds/milliseconds/microseconds/nanoseconds. Better use one specific configuration: seconds or milliseconds, etc. In case if multiple configurations are enabled, there are edge-cases (both seconds/milli from 1970).

type ParserOption

type ParserOption func(*Parser)

func AcceptAliases

func AcceptAliases() ParserOption

func AcceptUnixMicro

func AcceptUnixMicro() ParserOption

func AcceptUnixMilli

func AcceptUnixMilli() ParserOption

func AcceptUnixNano

func AcceptUnixNano() ParserOption

func AcceptUnixSeconds

func AcceptUnixSeconds() ParserOption

func GetParserDefaults

func GetParserDefaults() []ParserOption

func WithCustomAliases

func WithCustomAliases(customAliases map[string]func(time.Time) time.Time) ParserOption

func WithCustomClock

func WithCustomClock(c Clock) ParserOption

WithCustomClock opts to enable a custom Clock.

func WithLayouts

func WithLayouts(layouts ...string) ParserOption

type StdClock

type StdClock struct{}

func (*StdClock) Now

func (c *StdClock) Now() time.Time

type TimeNamedWaypointFile

type TimeNamedWaypointFile struct {
	*WaypointFile
	// contains filtered or unexported fields
}

TimeNamedWaypointFile is a Waypoint implementation for files/directories.

func NewTimeNamedWaypointFile

func NewTimeNamedWaypointFile(
	path string, fullLayout string,
	parentArg ...*TimeNamedWaypointFile,
) (*TimeNamedWaypointFile, error)

func (*TimeNamedWaypointFile) Time

func (w *TimeNamedWaypointFile) Time() time.Time

type TimeNamedWaypointFiles

type TimeNamedWaypointFiles []*TimeNamedWaypointFile

type TraverseDirection

type TraverseDirection string

TraverseDirection is a direction for traversing (e.g. past or future).

const (
	TraverseDirectionPast   TraverseDirection = "past"
	TraverseDirectionFuture TraverseDirection = "future"
)

type TraverseNodesMode

type TraverseNodesMode string

TraverseNodesMode specifies which type of nodes to traverse (e.g. leaves only or containers only).

const (
	TraverseLeavesOnly     TraverseNodesMode = "leaves_only"
	TraverseContainersOnly TraverseNodesMode = "containers_only"
	TraverseAllNodes       TraverseNodesMode = "all"
)

type TraverseOption

type TraverseOption func(*traverseConfig)

TraverseOption defines functional options for the Traverse function.

func O_ALL

func O_ALL() TraverseOption

O_ALL returns a TraverseOption for traversing all nodes.

func O_CONTAINERS_ONLY

func O_CONTAINERS_ONLY() TraverseOption

O_CONTAINERS_ONLY returns a TraverseOption for traversing only container nodes.

func O_FUTURE

func O_FUTURE() TraverseOption

O_FUTURE returns a TraverseOption for traversing in Future direction.

func O_LEAVES_ONLY

func O_LEAVES_ONLY() TraverseOption

O_LEAVES_ONLY returns a TraverseOption for traversing only leaf nodes.

func O_NON_CALENDAR

func O_NON_CALENDAR() TraverseOption

O_NON_CALENDAR returns a TraverseOption for including non calendar nodes.

func O_PAST

func O_PAST() TraverseOption

O_PAST returns a TraverseOption for traversing in Past direction.

type Voyager

type Voyager struct {
	// contains filtered or unexported fields
}

Voyager is a wrapper for a waypoint that allows for traversing through it.

func NewVoyager

func NewVoyager(root Waypoint, parserArg ...*Parser) *Voyager

func (*Voyager) Find

func (v *Voyager) Find(timeStr string) ([]Waypoint, error)

Find returns the all found Waypoints that match given time (as a string) e.g. Find("yesterday") returns all waypoints whose time is in the "yesterday" range.

func (*Voyager) Navigate

func (v *Voyager) Navigate(to string) (Waypoint, error)

Navigate returns the first found Waypoint that matches given time (as a string). E.g. Navigate("yesterday") returns waypoint corresponding to the yesterday's date.

func (*Voyager) Traverse

func (v *Voyager) Traverse(cb func(w Waypoint), opts ...TraverseOption) error

Traverse traverses through a given waypoint (all its children recursively).

type Waypoint

type Waypoint interface {
	// Identifier returns the identifier of the object.
	// E.g. for file waypoints it can be file path.
	Identifier() string

	// Time returns the time of the object.
	Time() time.Time

	// IsContainer returns true if the object can contain other objects.
	// E.g. for directories, it should return true.
	IsContainer() bool

	// Children returns the children of the object if it's a container.
	// E.g. for directories, it should return the list of files and directories inside.
	Children() []Waypoint
}

Waypoint is an interface for objects that have a time.

func AllChildren

func AllChildren(w Waypoint) []Waypoint

AllChildren is a helper function that gets ALL children of a waypoint (recursively).

func NewWaypointGroup

func NewWaypointGroup(identifier string, waypoints ...Waypoint) Waypoint

NewWaypointGroup create a group for given waypoints.

func WaypointGroupFromStrings

func WaypointGroupFromStrings(timeStrings []string, layoutArg ...string) Waypoint

func WaypointsFromStrings

func WaypointsFromStrings(timeStrings []string, layoutArg ...string) []Waypoint

type WaypointFile

type WaypointFile struct {
	// contains filtered or unexported fields
}

WaypointFile is a Waypoint implementation for files/directories.

func NewWaypointFile

func NewWaypointFile(path string, timeGetter func(timeSpec times.Timespec) time.Time) (*WaypointFile, error)

func (*WaypointFile) Children

func (w *WaypointFile) Children() []Waypoint

func (*WaypointFile) Identifier

func (w *WaypointFile) Identifier() string

func (*WaypointFile) IsContainer

func (w *WaypointFile) IsContainer() bool

func (*WaypointFile) Time

func (w *WaypointFile) Time() time.Time

type WaypointFiles

type WaypointFiles []*WaypointFile

type WaypointGroup

type WaypointGroup struct {
	// contains filtered or unexported fields
}

WaypointGroup stands for a simple implementation of Waypoint that is a container for other waypoints.

func (*WaypointGroup) Children

func (wg *WaypointGroup) Children() []Waypoint

func (*WaypointGroup) Identifier

func (wg *WaypointGroup) Identifier() string

func (*WaypointGroup) IsContainer

func (wg *WaypointGroup) IsContainer() bool

func (*WaypointGroup) Time

func (wg *WaypointGroup) Time() time.Time

Time returns group's time. For now group itself doesn't have a specific time. TODO(nice-to-have): this maybe configurable, e.g. no-time/min-time(children)/max-time(children)/time(children[0]), etc.

type WaypointString

type WaypointString struct {
	// contains filtered or unexported fields
}

WaypointString is a Waypoint implementation for a string that represents time.

func NewWaypointString

func NewWaypointString(v string, layoutArg ...string) *WaypointString

func (*WaypointString) Children

func (w *WaypointString) Children() []Waypoint

func (*WaypointString) Identifier

func (w *WaypointString) Identifier() string

func (*WaypointString) IsContainer

func (w *WaypointString) IsContainer() bool

func (*WaypointString) Time

func (w *WaypointString) Time() time.Time

func (*WaypointString) Voyager

func (w *WaypointString) Voyager(parserArg ...*Parser) *Voyager

type WaypointStrings

type WaypointStrings []*WaypointString

Jump to

Keyboard shortcuts

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