isoparse

package
v0.0.0-...-234afb8 Latest Latest
Warning

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

Go to latest
Published: Sep 27, 2018 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Overview

Package isoparse parses strings representing ISO-8601-conformant datetimes, dates, and times into instances of Go's time.Time.

Most of its parsing logic is ported directly from the isoparser module, authored by Paul Ganssle, within Python's dateutil library.

Unlike the parser in Go's time package, isoparser's functions do not require the precise format to be specified in advance.

It does not make every attempt to mirror Python's dateutil exactly, partially because of differences in behavior between Python and Go.

The isoparse package exports three parsing functions:

  • ParseISODatetime: parses a datetime (combined date and time string). Note that this function can also parse just a date in isolation, but if the user knows that input strings contain only dates with no time components, it will be faster to use ParseISODate.
  • ParseISODate: parses a date string with no time component.
  • ParseISOTime: parses a time string with no date component. This does not return a time.Time instance, but rather the hour/minute/second/nsec components and the location.

A Note On Time Zone Handling

Python's datetime has a concept of a naive datetime:

A naive object does not contain enough information to unambiguously locate itself relative
to other date/time objects.

This is useful in situations where, given a datetime string such as "2018-09-27T11:52:59", it is left up to the user to determine which time zone should added as an attribute, if any at all. Contrarily, Go's time.Date, which produces a time.Time instance, has a required location parameter whose nil value is UTC, and is an unexported struct field that cannot be changed independently of changing the timestamp itself.

For that reason:

  • All datetimes and times that lack a visible offset will have time.Local attached to them. This represents a "best assumption" that the datetime string is from the package user's local time zone.
  • This package also exports a simple function SetLoc that produces a new time.Time given a different time zone but the same timestamp components. This is different from Go's time.Time.In, time.Time.UTC, or time.Time.Local in that these conversions may change attributes such as t.Hour() in the resulting timestamp itself.

Note also that input strings that do contain a recognizable UTC offset will be given a loc that is the result of time.FixedZone, with the generic name of "UTC" and a specified seconds-east offset from UTC. There is no attempt to determine an IANA time zone by name because, for instance, an offset of -05:00 is still ambiguous based on whether daylight savings time is in effect or not.

Because time.Time.String() uses:

func (t Time) String() string {
	s := t.Format("2006-01-02 15:04:05.999999999 -0700 MST")
	...
}

The time.Time results from isoparse's parsing functions will have a loc that looks like time.FixedZone("UTC", secondsEast) and will be printed as:

YYYY-MM-DD HH:MM:SS.sssssssss -HHMM UTC

If you want more control over the actual resulting format, use time.Time.Format.

Conformance And Nonconformance To ISO-8601

isoparse conforms mostly to the December 2004 ISO Standard 8601 which cancels and replaces the second edition (ISO 8601:2000) with minor revisions. https://www.iso.org/standard/40874.html

For a (non-exhaustive) list of supported formats, execute the example function ExampleParseISODatetime from example_test.go to see a range of supported format examples.

The following is a list of ways in which this the exported functions in this package deviates from the ISO-8601:2004 standard:

  • The standard is strict about "T" being the separator between date and time. This package allows any ASCII character except 0 thru 9 as the separator between date and time, rather than just "T".
  • The standard allows years less than 0 and greater than 9999. This package only permits years greater than 0 and less than 10,000.
  • This package does not support parsing time intervals or recurring time intervals as defined in sections 4.4 and 4.5 of the standard, respectively.
  • The standard technically allows "19" to represent the date 1900-01-01, or "23" to represent the time 23:00:00, as "representation[s] with reduced accuracy." This package does not allow these formats. (Although YYYY-MM and YYYY are valid here.)
  • Unless otherwise note, this package does not support "expanded representations" for dates (sections 4.1.2.4, 4.1.3.3, 4.1.4.4).
  • Representations that "are only allowed by mutual agreement of the partners in information exchange" are generally not valid under this package.
  • Support for fractional components other than seconds is part of the ISO-8601 standard, but is not currently implemented in this parser. (This follows Python's dateutil.) For instance (from Wikipedia): "To denote '14 hours, 30 and one half minutes,' do not include a seconds figure. Represent it as '14:30,5', '1430,5', '14:30.5', or '1430.5'." These 4 datetime strings will return a ParseError from ParseISODatetime.

Other Notes

In addition to following closely with dateutil's isoparser module, this package also ports code from Python's native datetime module and Go's time package.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ParseISODate

func ParseISODate(dateString string) (time.Time, error)

ParseISODate parses an ISO-8601 date string with no time component and returns components.

func ParseISODatetime

func ParseISODatetime(datetime string) (time.Time, error)

ParseISODatetime parses an ISO-8601 datetime (combined date and time string).

It can also parse just a date in isolation, but if the user knows that input strings contain only dates with no time components, it will be faster to use ParseISODate.

This function is like Go's `time.Parse(layout, value string) (Time, error)`, except without the `layout` parameter. It attempts to otherwise follow the call syntax of `time.Parse` closely; if parse error is not nil, the returned Time will be 0001-01-01 00:00:00 +0000 UTC, i.e. time.Time{}.

If no timezone/offset is detected (either with 'Z' or an hh[:mm] offset), the result will have loc time.Local.

Example
fmt.Printf("%25v\t%25v\t%30v\n", "format", "string", "result")
fmt.Printf("%25v\t%25v\t%30v\n", "------", "------", "------")
for datetime, c := range allFormats {
	dt, _ := ParseISODatetime(datetime)
	fmt.Printf("%25v\t%25v\t%30v\n", c.f, datetime, dt)
}
Output:

func ParseISOTime

func ParseISOTime(timeString string) (components [4]int, tz *time.Location, err error)

ParseISOTime parses an ISO-8601 time string with no date component. Examples: HH, HH:MM or HHMM, HH:MM:SS or HHMMSS, HH:MM:SS.ssssss. (Plus an optional time zone portion.) `components` here represents hour, minute, second, nanosecond.

func SetLoc

func SetLoc(t time.Time, loc *time.Location) time.Time

Note that this differs from time.Time.In or time.Time.UTC in that it does not change the underlying timestamp components; it merely returns a new time.Time with the same year, month, ..., nsec components, but a different loc.

Types

type ParseError

type ParseError struct {
	Datetime string // This should always be passed
	Message  string // Treat as optional unless the reason is specific
}

ParseError describes any problem parsing a datetime, date, or time string. It is the sole error exported by this package. (It also exists with similar structure in Go's time package.)

func (*ParseError) Error

func (e *ParseError) Error() string

Jump to

Keyboard shortcuts

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