years

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jun 8, 2024 License: MIT Imports: 11 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("logs-U@000.log", "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 eugene@amberpixels.io

Documentation

Index

Constants

View Source
const (
	LayoutFormatUndefined LayoutFormat = iota
	// LayoutFormatGo is a format that is supported by Go time.Parse
	LayoutFormatGo = 1 << (iota - 1)
	// LayoutFormatUnixTimestamp is a format that parses time from Unix timestamp (seconds or milliseconds)
	LayoutFormatUnixTimestamp
)
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...)
}
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 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

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

func (LayoutFormat) String

func (lf LayoutFormat) String() string

type MutatingTime

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

MutatingTime is a wrapper of a standard time.Time so it can be mutated via helper methods

Example:

t, _ := time.Parse("...")
Mutate(&t).SomeModifyingMethod() // leads to update the t

func Mutate

func Mutate(v *time.Time) *MutatingTime

func (*MutatingTime) SetDay

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

SetDay overrides day of the time Note: Feb2 .SetDay(31) will lead to ~Mar2-3 (depending on days in Feb)

func (*MutatingTime) SetHour

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

SetHour overrides hour of the time

func (*MutatingTime) SetMinute

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

SetMinute overrides minute of the time

func (*MutatingTime) SetMonth

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

SetMonth overrides month of the time

func (*MutatingTime) SetNanosecond

func (t *MutatingTime) SetNanosecond(nanosecond int) *MutatingTime

SetNanosecond overrides nanosecond of the time

func (*MutatingTime) SetSecond

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

SetSecond overrides second of the time

func (*MutatingTime) SetYear

func (t *MutatingTime) SetYear(v int) *MutatingTime

SetYear overrides year of the time

func (*MutatingTime) Time

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

func (*MutatingTime) TruncateToDay

func (t *MutatingTime) TruncateToDay() *MutatingTime

TruncateToDay overrides hour, minute, second, 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) ParseAsTimestamp

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

ParseAsTimestamp parses given string as a timestamp (seconds/milliseconds/microseconds/nanoseconds)

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

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