A Go package for working with dates

date

GoDoc Build Status Coverage Status Go Report Card Issues

Package date provides functionality for working with dates.

This package introduces a light-weight Date type that is storage-efficient and convenient for calendrical calculations and date parsing and formatting (including years outside the [0,9999] interval).

It also provides

  • clock.Clock which expresses a wall-clock style hours-minutes-seconds with millisecond precision.
  • period.Period which expresses a period corresponding to the ISO-8601 form (e.g. "PT30S").
  • timespan.DateRange which expresses a period between two dates.
  • timespan.TimeSpan which expresses a duration of time between two instants.
  • view.VDate which wraps Date for use in templates etc.

See package documentation for full documentation and examples.

Installation

go get -u github.com/rickb777/date

or

dep ensure -add github.com/rickb777/date

Status

This library has been in reliable production use for some time. Versioning follows the well-known semantic version pattern.

Credits

This package follows very closely the design of package time in the standard library; many of the Date methods are implemented using the corresponding methods of the time.Time type and much of the documentation is copied directly from that package.

The original Good Work on which this was based was done by Filippo Tampieri at Fxtlabs.

Comments
  • Refactored NewWithWeeks implementation

    Refactored NewWithWeeks implementation

    Made a few changes:

    1. New2 renamed to NewWithWeeks (due to this branch changes and New2 func was never used in master)
    2. NewWithWeeks refactored for be more readable

    RFC)

  • Parsing duration is giving the value multiplied by 10

    Parsing duration is giving the value multiplied by 10

    https://github.com/rickb777/date/blob/c7dda9224f958b55c21026035f688df537b10b2d/period/parse.go#L220

    HI @rickb777. When I try to parse ISO8601 durations ex: PT1S, I am getting the seconds value as 10 instead of 1 due to that line of code.

  • When passing empty string to AutoParse it panics

    When passing empty string to AutoParse it panics

    Hi,

    I noticed that when passing "" to date.AutoParse, it panics with the following error:

      runtime error: index out of range
      /usr/local/Cellar/go/1.12.5/libexec/src/runtime/panic.go:44
    
      Full Stack Trace
      	/usr/local/Cellar/go/1.12.5/libexec/src/runtime/panic.go:522 +0x1b5
      github.com/petergtz/alexa-journal/vendor/github.com/rickb777/date.AutoParse(0x0, 0x0, 0x0, 0x0, 0x0)
      	/Users/pego/workspace/go/src/github.com/petergtz/alexa-journal/vendor/github.com/rickb777/date/parse.go:39 +0x4e4
      github.com/petergtz/alexa-journal.DateFrom(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0)
    

    Instead, I would expect it to return an error.

    Thank you, Peter

  • Wrong months calculation

    Wrong months calculation

    Hi all, in github.com/rickb777/[email protected] I have:

    p, err := period.Parse("P12M")
    if err != nil{
    	return nil, err
    }
    m1 := p.TotalMonthsApprox() //12 OK
    m2 := p.Months()// 0 KO
    

    From doc months() should returns the whole number of months in the period. I get 0

  • Allow for parsing larger intergers in Period strings

    Allow for parsing larger intergers in Period strings

    I recently was parsing numerous ISO-8601 strings with this library, but one string failed with a mysterious error: expected a number before the 'S' marker: PT31536000S.

    I debugged the code and realized that the problem wasn't a malformed ISO-8601 string, but the fact that strconv.ParseInt was called in date/period.parseDecimalFixedPoint() with a bitsize of 16. This meant the integer 31536000 overflowed the 16 bit size, so increasing the bitsize to 32 solved the issue.

    I'm not sure if there was a specific reason you used a 16 bitsize, I'm just making a PR because it's an easy fix and I you can't submit an issue to forks :/.

  • Add Support for Millisecond Level Accuracy

    Add Support for Millisecond Level Accuracy

    Because it would not be backwards compatible, I created new PeriodMS and PeriodMS64 structs for additional precision when converting to and from time.Duration which is necessary for an internal project our team is working on.

    Addresses the following issue: https://github.com/rickb777/date/issues/16

  • Security Issues with golang.org/x/text and golang.org/x/crypto

    Security Issues with golang.org/x/text and golang.org/x/crypto

  • Test failed on 32bit platforms

    Test failed on 32bit platforms

    Build tested on Fedora Rawhide with golang 1.15.2.

    Failed on i686 and armv7hl.

    + cd date-1.14.1
    + LDFLAGS=' -X github.com/rickb777/date/version=1.14.1'
    + GO_TEST_FLAGS='-buildmode pie -compiler gc'
    + GO_TEST_EXT_LD_FLAGS='-Wl,-z,relro -Wl,--as-needed  -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld  '
    + go-rpm-integration check -i github.com/rickb777/date -b /builddir/build/BUILD/date-1.14.1/_build/bin -s /builddir/build/BUILD/date-1.14.1/_build -V 1.14.1-1.fc34 -p /builddir/build/BUILDROOT/golang-github-rickb777-date-1.14.1-1.fc34.i386 -g /usr/share/gocode -r '.*example.*'
    Testing    in: /builddir/build/BUILD/date-1.14.1/_build/src
             PATH: /builddir/build/BUILD/date-1.14.1/_build/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/sbin
           GOPATH: /builddir/build/BUILD/date-1.14.1/_build:/usr/share/gocode
      GO111MODULE: off
          command: go test -buildmode pie -compiler gc -ldflags " -X github.com/rickb777/date/version=1.14.1 -extldflags '-Wl,-z,relro -Wl,--as-needed  -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld  '"
          testing: github.com/rickb777/date
    github.com/rickb777/date
    PASS
    ok  	github.com/rickb777/date	0.012s
    github.com/rickb777/date/clock
    PASS
    ok  	github.com/rickb777/date/clock	0.008s
    github.com/rickb777/date/gregorian
    PASS
    ok  	github.com/rickb777/date/gregorian	0.004s
    github.com/rickb777/date/period
    --- FAIL: TestPeriodScale (0.00s)
        arithmetic_test.go:56: 
            26 P10Y2.5D
            Expected
                <period.Period>: {years: -10, months: -90, days: -7, hours: 0, minutes: 0, seconds: 0}
            to equal
                <period.Period>: {years: 100, months: 0, days: 25, hours: 0, minutes: 0, seconds: 0}
    --- FAIL: TestParseErrors (0.00s)
        period_test.go:59: 
            24 PT103412160000S
            Expected
                <string>: PT103412160000S: expected a number but found 'S'
            to equal
                <string>: PT103412160000S: integer overflow occurred in seconds
    --- FAIL: TestParsePeriodWithNormalise (0.00s)
        period_test.go:104: 
            3 P3277D
            Expected
                <period.Period>: {years: -20, months: -90, days: -135, hours: 0, minutes: 0, seconds: 0}
            to equal
                <period.Period>: {years: 80, months: 110, days: 202, hours: 0, minutes: 0, seconds: 0}
    --- FAIL: TestNormaliseChanged (0.00s)
        period_test.go:843: 
            12: P468W.Normalise(false) expected -P2Y9M14.5D to equal P8Y11M19.2D
            Expected
                <period.Period>: {years: -20, months: -90, days: -145, hours: 0, minutes: 0, seconds: 0}
            to equal
                <period.Period>: {years: 80, months: 110, days: 192, hours: 0, minutes: 0, seconds: 0}
    FAIL
    exit status 1
    FAIL	github.com/rickb777/date/period	0.028s
    
  • feat: add period.ParseWithNormalise

    feat: add period.ParseWithNormalise

    This PR adds a period.ParseWithNormalise function that enables the caller to specify whether the returned period should be normalised or not.

    resolves #6.

  • period.Parse normalisation behaviour

    period.Parse normalisation behaviour

    Hi,

    I see that period.Parse implementation always normalises the parsed string but does not provide a means of overriding this behaviour. It would be really nice if we could have another Parse implementation where we could actually specify whether normalisation is desired or not.

    I am happy to come up with a PR if that sounds ok.

    Thanks.

  • Incorrect calculation

    Incorrect calculation

    It seems the duration is incorrectly calculated/formatted. Is this a known bug/behaviour?

    package main
    
    import (
    	"fmt"
    	"github.com/rickb777/date/period"
    	"time"
    )
    
    func main() {
    	const e = "PT30M67.6S"
    	d := (time.Minute * 30) + (time.Second * 67) + (time.Millisecond * 600)
    	p, _ := period.NewOf(d)
    	if p.String() != e {
    		fmt.Printf("expected %s, received %s", e, p)
    	}
    }
    
    

    expected PT30M67.6S, received PT31M7.6S

    Play(play.golang.org)

  • Calling period.AddTo(time) in a loop stops and repeats

    Calling period.AddTo(time) in a loop stops and repeats

    Greetings,

    I'm experiencing an issue where when i call period.AddTo in a loop it reaches a certain date and then repeats.

    Not sure how else to describe it.

    Here is a code example: https://gist.github.com/zeroallox/1fb3812ec6572c39cad670d59eacd486

    When i run this, dates will print in sequence correctly up until 2020-11-01 01:00:00 -0500 EST and then start repeating.

    Thanks for your time and this wonderful library.

    🍍

  • Support for combination of positive and negative durations in period.Parse

    Support for combination of positive and negative durations in period.Parse

    This appears to be a feature of ISO-8601 which is supported in some frameworks, like PostgreSQL. If it was also supported in this package, it would make interaction with such frameworks easier.

    I have not bought access to ISO-8601, so my reference is only second-hand from the PostgreSQL community (https://www.postgresql.org/message-id/9q0ftb37dv7.fsf%40gmx.us):

    | EXAMPLE 5 'P-3M-3DT1HSM', duration of three months and three days in the reverse direction, with one hour | and five minutes in the original direction.

    Such strings are produced by PostgreSQL's interval type when intervaltype set to iso_8601. Managing this type is already a challenge in golang, so it would be all the more useful to be able to parse them using this package.

    Test case:

    p1, err := period.Parse("P1DT-18H")
    if err != nil {
    	fmt.Fatalln(err)
    }
    

    Output:

    P1DT-18H: expected a number but found '-'
    

    It appears that negative and positive durations can already be added and handled (and printed) correctly. My workaround will be to try and split up the parts of the string and modify, parse and add them individually. It would be wonderful if period.Parse could handle this in future versions.

  • Only the last field can have a fraction check doesn't always work

    Only the last field can have a fraction check doesn't always work

    The program below prints P3.5YT5.3S: 'Y' & 'S' only the last field can have a fraction because P3.5Y6M4DT12H30M5.3S passes the check, although I'm guessing it shouldn't.

    package main
    
    import "github.com/rickb777/date/period"
    
    func main() {
            _, err := period.Parse("P3.5Y6M4DT12H30M5.3S", false)
            if err != nil {
                    println(err.Error())
            }
    
            _, err = period.Parse("P3.5YT5.3S", false)
            if err != nil {
                    println(err.Error())
            }
    }
    

    PS: Thank you for putting in the time to write this library!

  • Between function fails if one argument is time.Now

    Between function fails if one argument is time.Now

    I tried getting a period between two dates, one of which is the current time.

    year := 2021
    month := 3
    
    now := time.Now()
    p := period.Between(time.Date(int(year), time.Month(month), 1, 0, 0, 0, 0, now.Location()), now)
    

    However, this panics with the statement: Periods must have homogeneous signs; got P0Y0M0W190DT19H3M44S

    For reference, this was generated at 2021-09-07 19:07:43.2612391 +0900 JST m=+0.109965201 but this was not the only time which generated this panic. What exactly does it mean for a period to not have a homogeneous sign and how can I fix this?

  • Integer overflow

    Integer overflow

    This package introduces a light-weight Date type that is storage-efficient and convenient for calendrical calculations and date parsing and formatting (including years outside the [0,9999] interval).

    This statement from the docs is misleading. Attempt to parse any date with numbers greater than (1 << 15) / 10 - 1 (e.g. P3276Y) will result into the integer overflow error. In order to support such dates you need either to split decimal part into a separate field(s) or use at least int32 to store values.

    Just in case, if you're interested, I've implemented int32 approach in the fork: https://github.com/simplylizz/date

Related tags
Go package for calculating the sunrise and sunset times for a given location

go-sunrise Go package for calculating the sunrise and sunset times for a given location based on this method. Usage To calculate sunrise and sunset ti

Dec 13, 2022
Golang package to manipulate time intervals.

timespan timespan is a Go library for interacting with intervals of time, defined as a start time and a duration. Documentation API Installation Insta

Sep 26, 2022
timeutil - useful extensions (Timedelta, Strftime, ...) to the golang's time package

timeutil - useful extensions to the golang's time package timeutil provides useful extensions (Timedelta, Strftime, ...) to the golang's time package.

Dec 22, 2022
Go's missing DateTime package

Go's standard library contains a single date package - time. The type provided by it, Time, contains date, time and location information.

Nov 19, 2022
A simple, semantic and developer-friendly golang package for datetime

Carbon 中文 | English carbon 是一个轻量级、语义化、对开发者友好的 Golang 时间处理库,支持链式调用和 gorm、xorm、zorm 等主流 orm。 如果您觉得不错,请给个 star 吧 github:github.com/golang-module/carbon g

Jan 9, 2023
Structural time package for jalali calendar

Jalali Structural time package for jalali calendar. This package support parse from string, json and time. Structures There are three data structures

Mar 21, 2022
Timediff is a Go package for printing human readable, relative time differences 🕰️

timediff is a Go package for printing human readable, relative time differences. Output is based on ranges defined in the Day.js JavaScript library, and can be customized if needed.

Dec 25, 2022
A Go package for working with dates

date Package date provides functionality for working with dates. This package introduces a light-weight Date type that is storage-efficient and coveni

May 24, 2022
CSPFinder is a tool to compare ROI of selling Cash Secure Put options between different tickers for different expiry dates.

CSPFinder is a tool to compare ROI of selling Cash Secure Put options between different tickers for different expiry dates. It is intended to help open new cash secured put positions.

Dec 21, 2021
A simple cli tool to convert unix timestamps or human readable dates.

now A simple cli tool to convert unix timestamps or human readable dates. Install go install github.com/gloomyzerg/now Usage now #output now unix time

Nov 23, 2021
Convert dates from or to 31 calendars in Go. Implements the functions discussed in Reingold/Dershowitz 2018.

libcalcal - Calendrical calculations in Go About libcalcal implements in Go the functions described and presented in: Reingold, Edward M., and Nachum

Dec 30, 2021
Go package providing opinionated tools and methods for working with the `aws-sdk-go/service/cloudfront` package.

go-aws-cloudfront Go package providing opinionated tools and methods for working with the aws-sdk-go/service/cloudfront package. Documentation Tools $

Feb 2, 2022
go.rice is a Go package that makes working with resources such as html,js,css,images,templates, etc very easy.

go.rice go.rice is a Go package that makes working with resources such as html,js,css,images and templates easy. During development go.rice will load

Dec 29, 2022
A Go filesystem package for working with files and directories

Stowage A Go filesystem package for working with files and directories, it features a simple API with support for the common files and directories ope

May 28, 2021
Yet another Go package for working with *.golden test files, with a focus on simplicity.

go-golden Yet another Go package for working with *.golden test files, with a focus on simplicity. Import import "github.com/jimeh/go-golden" Usage fu

Aug 3, 2022
Go package providing tools for working with Library of Congress data.

go-libraryofcongress Go package providing tools for working with Library of Congress data. Documentation Tools $> make cli go build -mod vendor -o bin

Jan 3, 2023
Go package for working with Library of Congress data in an SFO Museum context.

go-sfomuseum-libraryofcongress Go package for working with Library of Congress data in an SFO Museum context. Documentation Documentation is incomplet

Oct 19, 2021
This is an experimental package for working with JSON-LD documents in Go

JSON-LD ?? Simple JSON-LD in Go This is an experimental package for working with JSON-LD documents in Go. Experimental, Pre-Alpha Quality Please do no

Jul 6, 2022
A golang package for comparing and working with k0s version numbers

version A go-language package for managing k0s version numbers. It is based on hashicorp/go-version but adds sorting and comparison capabilities for t

Feb 7, 2022