gotime

package module
v0.0.0-...-847d61e Latest Latest
Warning

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

Go to latest
Published: Sep 26, 2018 License: MIT Imports: 6 Imported by: 0

README

Gotime Build Status Coverage Status Documentation Code Size Go Report Card GitHub issues license

A small library of useful extensions to Golang's time package

Documentation

Use the Source! The package comment has additional details; all in all, we're just trying to keep the docs DRY.

700mb Overview

If there's one thing computers are bad at, it's working with dates. On the one hand, we have libraries such as moment.js which give us basic functionality that is mostly already present in Go. On the other hand, though, there's a lot of functionality that would be nice to have, such as parsing JSON dates that aren't accurate to the millisecond or anything involving workdays. This library also aims to provide convenience functions (aren't all functions really just convenience functions?) for finding and comparing dates.

Help Us Grow

If you have functionality that you'd like to add to this library or decouple from an app, feel free to open a feature request with some sample code. If you have a great idea, we'd love to hear about it! If your timing is serendipitous, I'll write it myself.

Issues/Contributions

  • Fork the repo
  • Create a feature branch or don't, it doesn't matter- it's your repo.
  • Write your tests or ask for help doing so (I use Ginkgo)
  • Write your functionality
  • Open a PR

Failure to participate in step 3 will result in me fixing your code and commenting judiciously on your inability to write decent software in comments that will appear in godoc. The first result on Google for your username won't be very flattering.

Documentation

Overview

Package gotime adds some handy functionality to the Golang time package.

One of the main functions of this library is parsing ISO-8601 dates that do not include the full RFC3339 format. For example, something like time.Time.UnmarshalJSON("2018-07-14") will fail, whereas something like time.Time.UnmarshalJSON("2018-04-14 08:23:35Z") will succeed. The format constraints this library uses came from https://en.wikipedia.org/wiki/ISO_8601 on 2018-195T10-05.

The functions in equality.go ({Date,Time}Equals* and SameTime) can be used to compare part of a time.Time, for example to see if the dates are the same irrespective of the time zone or if just the time portion is the same down to the second.

search.go contains functions for finding the first, last, and nth occurrence of a particular day in a month. These are handy, for example, when figuring out the date of a holiday such as Thanksgiving in the United States.

The word "format" is used herein to mean "a valid first argument to time.Parse()".

The Get{Date,Time}Format functions interrogate their string parameter, which should be an ISO-8601-compatible string, to determine the proper parsing format if possible. The difference between the Fast and Safely functions is that the former assume the input is valid while the latter will error if not. The Fast functions are fast because they use as few rudimentary string functions as possible to narrow down the possibilities and do no verification of the source value. The Safely functions are safer because they use regular expressions and determine the type using the "if it quacks like a duck" method, however they would not prevent you from passing a time like 99:00

Be sure to pass the entire timestamp to each function. The DateParser and TimeParser variables are set to the Fast functions by default, and this library uses those variables internally to determine which set of functions to use.

Index

Examples

Constants

This section is empty.

Variables

View Source
var DateParser = GetDateFormatFast

DateParser specifies a function that returns the date format of an ISO timestamp.

View Source
var TimeParser = GetTimeFormatFast

TimeParser specifies a function that returns the time format of an ISO timestamp.

Functions

func DateEquals

func DateEquals(a, b time.Time) bool

DateEquals determines whether the date portion of two Times are equal. This function considers two times with the same year and the same day of the year to be identical, ignoring time zones. Use DateEqualsTZ if you're concerned about time zones.

func DateEqualsTZ

func DateEqualsTZ(a, b time.Time) bool

DateEqualsTZ extends DateEquals by converting both times to UTC. After calling UTC() on both times, this function calls DateEquals internally and returns the result.

func FirstWeekday

func FirstWeekday(year int, month time.Month, day time.Weekday) time.Time

FirstWeekday returns a UTC time.Time representing the first <day> in <month>.

func GetDateFormatFast

func GetDateFormatFast(str string) (string, error)

GetDateFormatFast attempts to find the date format. Fast. Being as such it uses fuzzy matching, such as the number of hyphens, to determine the format: it does not ensure the string conforms to the format. For example, input of "200-100-50" would return "2006-01-02", and input of "10000000" would return "20060102". Do not use this function if you are unsure that your string contains a valid date. Valid options: --MM-DD, --MMDD, YYYY-MM-DD, YYYY-MM, YYYY, YYYYMMDD Currently invalid: YYYY-Www, YYYY-DDD, YYYYDDD

func GetDateFormatSafely

func GetDateFormatSafely(str string) (string, error)

GetDateFormatSafely uses regexes to parse date formats. *NOT IMPLEMENTED Using this function ensures the returned format string will work correctly. Use this function when you are unsure if your date is properly formatted.

func GetTimeFormatFast

func GetTimeFormatFast(str string) (string, error)

GetTimeFormatFast tries to find the time and TZ format. Fast. Being as such it uses fuzzy matching, such as the number of colons, to determine the format: it does not ensure the string conforms to the format. For example, input of "50:60:70" would return "15:04:05", and input of "T99-" would return "20060102". Do not use this function if you are unsure that your string contains a valid time.

Valid times: HH:MM:SS, HH:MM, HH:MM:SS.nnn, hh, hhmm, hhmmss, hhmmss.nnn, any of the previous postfixed with Z or +/-hh(:mm)?

func GetTimeFormatSafely

func GetTimeFormatSafely(str string) (string, error)

GetTimeFormatSafely uses regexes to parse date formats. *NOT IMPLEMENTED Using this function ensures the returned format string will work correctly. Use this function when you are unsure if your time is properly formatted.

func LastWeekday

func LastWeekday(year int, month time.Month, day time.Weekday) time.Time

LastWeekday returns a UTC time.Time representing the last <day> in <month>.

func NthWeekday

func NthWeekday(year int, month time.Month, n int, day time.Weekday) time.Time

NthWeekday returns a UTC time.Time representing the nth weekday of a month. The month is determined by the year and month parameters, `n` is the week number, and day is the day. As this function uses time.Time.Add() internally, if you ask for, for example, the 20th Saturday, you'll receive a time.Time a few months in the future. The times must be in UTC for calculating times around daylight savings time.

Example
package main

import (
	"fmt"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	. "github.com/onwsk8r/gotime"
)

// nolint: dupl
var _ = Describe("Search Functions", func() {
	Describe("NthWeekday", func() {
		It("should find MLK Day", func() {
			exp := time.Date(2018, time.January, 15, 0, 0, 0, 0, time.UTC)
			res := NthWeekday(2018, time.January, 3, time.Monday)
			Expect(res.Equal(exp)).To(BeTrue())
			Expect(res.Format("20060102")).To(Equal("20180115"))
		})
		It("should find the day this test was written", func() {
			exp := time.Date(2018, time.August, 26, 0, 0, 0, 0, time.UTC)
			res := NthWeekday(2018, time.August, 4, time.Sunday)
			Expect(res.Equal(exp)).To(BeTrue())
			Expect(res.Format("20060102")).To(Equal("20180826"))
		})
		It("should find Thanksgiving", func() {
			exp := time.Date(2018, time.November, 22, 0, 0, 0, 0, time.UTC)
			res := NthWeekday(2018, time.November, 4, time.Thursday)
			fmt.Println(res.String())
			Expect(res.Equal(exp)).To(BeTrue())
			Expect(res.Format("20060102")).To(Equal("20181122"))
		})
	})

	Describe("FirstWeekday", func() {
		It("should find the first Saturday of a month that starts on Saturday", func() {
			exp := time.Date(2018, time.September, 1, 0, 0, 0, 0, time.UTC)
			res := FirstWeekday(2018, time.September, time.Saturday)
			Expect(res.Equal(exp)).To(BeTrue())
			Expect(res.Format("20060102")).To(Equal("20180901"))
		})
		It("should find the first Friday of a month that starts on Saturday", func() {
			exp := time.Date(2018, time.September, 7, 0, 0, 0, 0, time.UTC)
			res := FirstWeekday(2018, time.September, time.Friday)
			Expect(res.Equal(exp)).To(BeTrue())
			Expect(res.Format("20060102")).To(Equal("20180907"))
		})
	})

	Describe("LastWeekday", func() {
		It("should find the last Sunday of a month that starts on Saturday", func() {
			exp := time.Date(2018, time.September, 30, 0, 0, 0, 0, time.UTC)
			res := LastWeekday(2018, time.September, time.Sunday)
			Expect(res.Equal(exp)).To(BeTrue())
			Expect(res.Format("20060102")).To(Equal("20180930"))
		})
		It("should find the last Friday of a month that starts on Saturday", func() {
			exp := time.Date(2018, time.September, 28, 0, 0, 0, 0, time.UTC)
			res := LastWeekday(2018, time.September, time.Friday)
			Expect(res.Equal(exp)).To(BeTrue())
			Expect(res.Format("20060102")).To(Equal("20180928"))
		})
		It("should find the last Monday of a month that starts on Saturday", func() {
			exp := time.Date(2018, time.September, 24, 0, 0, 0, 0, time.UTC)
			res := LastWeekday(2018, time.September, time.Monday)
			Expect(res.Equal(exp)).To(BeTrue())
			Expect(res.Format("20060102")).To(Equal("20180924"))
		})
		It("should find the last day of a 31-day month", func() {
			exp := time.Date(2018, time.August, 31, 0, 0, 0, 0, time.UTC)
			res := LastWeekday(2018, time.August, time.Friday)
			Expect(res.Equal(exp)).To(BeTrue())
			Expect(res.Format("20060102")).To(Equal("20180831"))
		})
	})
})

func main() {
	year := 2018
	month := time.September
	n := 3
	day := time.Monday

	res := NthWeekday(year, month, n, day)
	fmt.Println("The third Monday in September is", res.Format("2006-01-02"))
}
Output:

The third Monday in September is 2018-09-17

func Parse

func Parse(str string) (time.Time, error)

Parse is like a patternless version of time.Parse. It uses the package specified pattern finding functions to determine the pattern and then calls time.Parse internally.

func SameTime

func SameTime(a, b time.Time) bool

SameTime determines whether two times refer to the same time, down to the second. This is achieved by comparing the Unix timestamps of each time. For a more accurate comparison, consider using time.Time.Equal(), which compares nanoseconds.

func TimeEquals

func TimeEquals(a, b time.Time) bool

TimeEquals determines whether the time portion of two Times are equal. This function comapres the hours, minutes, and seconds, ignoring nanoseconds and time zones. If those are important to you, use the appropriate function.

func TimeEqualsNS

func TimeEqualsNS(a, b time.Time) bool

TimeEqualsNS extends TimeEquals by comparing nanoseconds as well.

func TimeEqualsNSTZ

func TimeEqualsNSTZ(a, b time.Time) bool

TimeEqualsNSTZ extends TimeEqualsNS by converting both times to UTC. After the convertions, this function returns the value of TimeEqualsNS.

func TimeEqualsTZ

func TimeEqualsTZ(a, b time.Time) bool

TimeEqualsTZ extends TimeEquals by converting both times to UTC. After calling UTC() on both times, this function calls TimeEquals internally and returns the result.

Types

type Equalizer

type Equalizer func(a, b time.Time) bool

Equalizer abstracts the Gotime comparison functions

type ParseError

type ParseError struct {
	From    string
	Problem string
	errors.Err
}

ParseError represents an error parsing a time string. The string being parsed is stored in the From property and a description of what exactly went wrong is stored in the Problem property. This type is exported for use in tests such as `err, ok := err.(gotime.ParseError)`.

func NewParseError

func NewParseError(from, prob string) *ParseError

NewParseError creates a new ParseError. While this function is exported in case this package should grow to have other packages inside it, you should probably avoid using it in your own code unless you want to confuse people. The first parameter is the string that was being parsed and the second parameter is a description of what went wrong (eg "† is not a valid date")

func (*ParseError) Error

func (p *ParseError) Error() string

Error fulfills the error interface. It prints both the Problem and the string that caused it (From).

type Time

type Time struct {
	time.Time
	OriginalFormat string
}

Time implements and extends time.Time

func (*Time) MarshalJSON

func (t *Time) MarshalJSON() ([]byte, error)

MarshalJSON implements the json.Marshaler interface. The time will be in OriginalFormat if set. If OriginalTime is not set, the function will fall back to time.time.MarshalJSON().

func (*Time) Scan

func (t *Time) Scan(value interface{}) error

Scan implements the sql.Scanner interface

func (*Time) UnmarshalJSON

func (t *Time) UnmarshalJSON(data []byte) error

UnmarshalJSON implements the json.Unmarshaler interface. The time can be in any format.

func (*Time) UnmarshalText

func (t *Time) UnmarshalText(data []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface. The time can be in any format.

func (*Time) Value

func (t *Time) Value() (driver.Value, error)

Value returns the embedded time.Time for use with SQL queries

Directories

Path Synopsis
Package holiday contains functions for working with holidays.
Package holiday contains functions for working with holidays.

Jump to

Keyboard shortcuts

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