edtf

package module
v1.1.1 Latest Latest
Warning

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

Go to latest
Published: May 20, 2022 License: BSD-3-Clause Imports: 4 Imported by: 19

README

go-edtf

A Go package for parsing Extended DateTime Format (EDTF) date strings. It is compliant with Level 0, Level 1 and Level 2 of the EDTF specification (2019).

Go Reference

At this time Go reference documentation is incomplete.

Background

The following is taken from the EDTF website:

EDTF defines features to be supported in a date/time string, features considered useful for a wide variety of applications

Date and time formats are specified in ISO 8601, the International Standard for the representation of dates and times. ISO 8601-2004 provided basic date and time formats; these were not sufficiently expressive to support various semantic qualifiers and concepts than many applications find useful. For example, although it could express the concept "the year 1984", it could not express "approximately the year 1984", or "we think the year is 1984 but we're not certain". These as well as various other concepts had therefore often been represented using ad hoc conventions; EDTF provides a standard syntax for their representation.

Further, 8601 is a complex specification describing a large number of date/time formats, in many cases providing multiple options for a given format. Thus a second aim of EDTF is to restrict the supported formats to a smaller set.

EDTF functionality has now been integrated into ISO 8601-2019, the latest revision of ISO 8601, published in March 2019.

EDTF was developed over the course of several years by a community of interested parties, and a draft specification was published in 2012. The draft specification is no longer publicly, readily available, because its availability has caused confusion with the official version.

Features

Level 0
Name Implementation Tests Notes
Date yes yes
Date and Time yes yes
Time Interval yes yes
Level 1
Name Implementation Tests Notes
Letter-prefixed calendar year yes yes Calendar years greater (or less) than 9999 are not supported yet.
Season yes yes
Qualification of a date (complete) yes yes
Unspecified digit(s) from the right yes yes
Extended Interval (L1) yes yes
Negative calendar year yes yes
Level 2
Name Implementation Tests Notes
Exponential year yes yes Calendar years greater (or less) than 9999 are not supported yet.
Significant digits yes yes
Sub-year groupings yes yes Compound phrases, like "second quarter of 2001" are not supported yet.
Set representation yes yes
Qualification yes yes
Unspecified Digit yes yes Years with a leading unspecified digit, for example "X999", are not supported yet
Interval yes yes

Nomenclature and Type Definitions

Date Spans (or edtf.EDTFDate)

The word span is defined as:

The full extent of something from end to end; the amount of space that something covers:

An edtf.EDTFDate instance is a struct that represents a date span in the form of Start and End properties which are themselves edtf.DateRange instances. It also contains properties denoting the EDTF feature and level associated with EDTF string used to create the instance.

type EDTFDate struct {
	Start   *DateRange `json:"start"`
	End     *DateRange `json:"end"`
	EDTF    string     `json:"edtf"`
	Level   int        `json:"level"`
	Feature string     `json:"feature"`
}
Date ranges (or edtf.DateRange)

The word range is defined as:

The area of variation between upper and lower limits on a particular scale

A edtf.DateRange instance encompasses upper and lower dates (for an EDTF string). It is a struct with Lower and Upper properties which are themselves edtf.Date instances.

type DateRange struct {
	EDTF  string `json:"edtf"`
	Lower *Date  `json:"lower"`
	Upper *Date  `json:"upper"`
}
Date (or edtf.Date)

A edtf.Date instance is the upper or lower end of a date range. It is a struct that contains atomic date and time information as well as a number of flags denoting precision and other granularities defined in the EDTF specification.

type Date struct {
	DateTime    string     `json:"datetime,omitempty"`
	Timestamp   *Timestamp `json:"timestamp,omitempty"`
	YMD         *YMD       `json:"ymd"`
	Uncertain   Precision  `json:"uncertain,omitempty"`
	Approximate Precision  `json:"approximate,omitempty"`
	Unspecified Precision  `json:"unspecified,omitempty"`
	Precision   Precision  `json:"precision,omitempty"`
	Open        bool       `json:"open,omitempty"`
	Unknown     bool       `json:"unknown,omitempty"`
	Inclusivity Precision  `json:"inclusivity,omitempty"`
}
Notes
  • DateTime strings are encoded as RFC3339 strings, in UTC.
Timestamp (or edtf.Timestamp)

A edtf.Timestamp instance represents the Unix timestamp for the date. When serialized (or "marshal-ed") as JSON a edtf.Timestamp instance is encoded as a signed 64-bit integer. When a JSON-encoded edtf.EDTFDate is unserialized (or "unmarshal"-ed) the integer is converted to a edtf.Timestamp instance.

The Timestamp is defined as a custom struct rather than an integer so that when it is serialized there is no confusion about whether a value of "0" means "January 1, 1970" or "this property is missing". It means the former. If the property is nil then it should be excluded from the JSON representation entirely.

Because the Go language imposes limits on the minimum and maximum date it can represent (-9999 and 9999 respectively) this element may be nil.

YMD (or edtf.YMD)

A `edtf.YMD instance a struct containing numeric year, month and day properties. It is designed to supplement "time" elements or, in cases where a "time" element is not possible to replace it.

type YMD struct {
	Year  int `json:"year"`
	Month int `json:"month"`
	Day   int `json:"day"`
}
Precision (or edtf.Precision)

"Precision" a 32-bit integer (as well as a Go language Precision instance with its own method) that uses bitsets to represent granularity.

The following named granularities are defined as constants:

Name Value Notes
NONE 0
ALL 2
ANY 4
DAY 8
WEEK 16
MONTH 32
YEAR 64
DECADE 128
CENTURY 256
MILLENIUM 512

Documentation

Proper Go language documentation is incomplete but can be viewed in its current state at: https://godoc.org/github.com/sfomuseum/go-edtf

Example

package main

import (
	"flag"
	"github.com/sfomuseum/go-edtf/parser"
	"log"
)

func main() {

	flag.Parse()

	for _, raw := range flag.Args() {

		if !parser.IsValid(raw){
			continue
		}

		level, feature, _ := parser.Matches(raw)

		log.Printf("%s is a Level %d (%s) string\n", raw, level, feature)
		
		d, _ := parser.ParseString(raw)

		log.Printf("%s span %v to %v\n", d.Lower(), d.Upper())
	}
}

Error handling removed for the sake of brevity.

Tools

To build binary versions of these tools run the cli Makefile target. For example:

$> make cli
go build -mod vendor -o bin/parse cmd/parse/main.go
go build -mod vendor -o bin/matches cmd/matches/main.go
matches

Parse one or more EDTF strings and emit the EDTF level and feature name they match.

> ./bin/matches -h
Parse one or more EDTF strings and emit the EDTF level and feature name they match.
Usage:
	 ./bin/matches edtf_string(N) edtf_string(N)

For example:

> ./bin/matches 193X 2021-10-10T00:24:00Z
193X level 1 (Unspecified digit(s) from the right)
2021-10-10T00:24:00Z level 0 (Date and Time)
parse

Parse one or more EDTF strings and return a list of JSON-encoded edtf.EDTFDate objects.

$> ./bin/parse -h
Parse one or more EDTF strings and return a list of JSON-encoded edtf.EDTFDate objects.
Usage:
	 ./bin/parse edtf_string(N) edtf_string(N)

For example:

$> ./bin/parse 2004-06-XX/2004-07-03 '{1667,1668,1670..1672}' | jq

[
  {
    "start": {
      "edtf": "2004-06-XX",
      "lower": {
        "datetime": "2004-06-01T00:00:00Z",
        "timestamp": 1086048000,
        "ymd": {
          "year": 2004,
          "month": 6,
          "day": 1
        },
        "precision": 32
      },
      "upper": {
        "datetime": "2004-06-30T23:59:59Z",
        "timestamp": 1088639999,
        "ymd": {
          "year": 2004,
          "month": 6,
          "day": 30
        },
        "precision": 32
      }
    },
    "end": {
      "edtf": "2004-07-03",
      "lower": {
        "datetime": "2004-07-03T00:00:00Z",
        "timestamp": 1088812800,
        "ymd": {
          "year": 2004,
          "month": 7,
          "day": 3
        },
        "precision": 64
      },
      "upper": {
        "datetime": "2004-07-03T23:59:59Z",
        "timestamp": 1088899199,
        "ymd": {
          "year": 2004,
          "month": 7,
          "day": 3
        },
        "precision": 64
      }
    },
    "edtf": "2004-06-XX/2004-07-03",
    "level": 2,
    "feature": "Interval"
  },
  {
    "start": {
      "edtf": "1667",
      "lower": {
        "datetime": "1667-01-01T00:00:00Z",
        "timestamp": -9561715200,
        "ymd": {
          "year": 1667,
          "month": 1,
          "day": 1
        },
        "precision": 64,
        "inclusivity": 2
      },
      "upper": {
        "datetime": "1667-12-31T23:59:59Z",
        "timestamp": -9530179201,
        "ymd": {
          "year": 1667,
          "month": 12,
          "day": 31
        },
        "precision": 64,
        "inclusivity": 2
      }
    },
    "end": {
      "edtf": "1672",
      "lower": {
        "datetime": "1672-01-01T00:00:00Z",
        "timestamp": -9403948800,
        "ymd": {
          "year": 1672,
          "month": 1,
          "day": 1
        },
        "precision": 64,
        "inclusivity": 2
      },
      "upper": {
        "datetime": "1672-12-31T23:59:59Z",
        "timestamp": -9372326401,
        "ymd": {
          "year": 1672,
          "month": 12,
          "day": 31
        },
        "precision": 64,
        "inclusivity": 2
      }
    },
    "edtf": "{1667,1668,1670..1672}",
    "level": 2,
    "feature": "Set representation"
  }
]

Tests

Tests are defined and handled in (3) places:

  • In every level(N) package there are individual _test.go files for each feature.
  • In every level(N) package there is a tests.go file that defines input values and expected response values defined as tests.TestResult instances.
  • The tests.TestResult instance, its options and its methods are defined in the tests package. It implements a TestDate method that most of the individual _test.go files invoke.

Reporting Bugs and Issues

There might still be bugs, implementation gotchas or other issues. If you encounter any of these please report them here.

See also

Documentation

Overview

package edtf provides method for parsing Extended DateTime Format (EDTF) date strings. It is compliant with Level 0, Level 1 and Level 2 of the EDTF specification (2019).

Index

Constants

View Source
const APPROXIMATE string = "~"
View Source
const HMS_LOWER string = "00:00:00"
View Source
const HMS_UPPER string = "23:59:59"
View Source
const MAX_YEARS int = 9999 // This is a Golang thing
View Source
const NEGATIVE string = "-"
View Source
const OPEN string = ".."
View Source
const OPEN_2012 string = "open"
View Source
const UNCERTAIN string = "?"
View Source
const UNCERTAIN_AND_APPROXIMATE string = "%"
View Source
const UNKNOWN string = UNSPECIFIED // this code was incorrectly referring to "unspecified" as "unknown"
View Source
const UNKNOWN_2012 string = UNSPECIFIED_2012
View Source
const UNSPECIFIED string = ""
View Source
const UNSPECIFIED_2012 string = "uuuu"

Variables

This section is empty.

Functions

func Invalid

func Invalid(label string, edtf_str string) error

func IsDeprecated added in v1.0.0

func IsDeprecated(str string) bool

IsDeprecated returns a boolean flag indicating whether 'str' is considered a deprecated EDTF value.

func IsInvalid

func IsInvalid(e error) bool

func IsNotImplemented

func IsNotImplemented(e error) bool

func IsNotSet added in v0.2.0

func IsNotSet(e error) bool

func IsOpen added in v0.3.0

func IsOpen(s string) bool

Return a boolean value indicating whether a string is considered to be an "open" EDTF date.

func IsUnknown added in v0.3.0

func IsUnknown(s string) bool

Return a boolean value indicating whether a string is considered to be an "unknown" EDTF date.

func IsUnrecognized added in v0.2.0

func IsUnrecognized(e error) bool

func IsUnspecified added in v0.3.0

func IsUnspecified(s string) bool

Return a boolean value indicating whether a string is considered to be an "unspecified" EDTF date.

func IsUnsupported

func IsUnsupported(e error) bool

func NotImplemented

func NotImplemented(label string, edtf_str string) error

func NotSet added in v0.2.0

func NotSet() error

func ReplaceDeprecated added in v1.0.0

func ReplaceDeprecated(old string) (string, error)

ReplaceDeprecated returns the current value for 'old'.

func Unrecognized added in v0.2.0

func Unrecognized(label string, edtf_str string) error

func Unsupported

func Unsupported(label string, edtf_str string) error

Types

type Date

type Date struct {
	DateTime    string     `json:"datetime,omitempty"`
	Timestamp   *Timestamp `json:"timestamp,omitempty"`
	YMD         *YMD       `json:"ymd"`
	Uncertain   Precision  `json:"uncertain,omitempty"`
	Approximate Precision  `json:"approximate,omitempty"`
	Unspecified Precision  `json:"unspecified,omitempty"`
	Precision   Precision  `json:"precision,omitempty"`
	Open        bool       `json:"open,omitempty"`
	Unknown     bool       `json:"unknown,omitempty"`
	Inclusivity Precision  `json:"inclusivity,omitempty"`
}

func (*Date) SetTime added in v0.2.0

func (d *Date) SetTime(t *time.Time)

func (*Date) String

func (d *Date) String() string

type DateRange

type DateRange struct {
	EDTF  string `json:"edtf"`
	Lower *Date  `json:"lower"`
	Upper *Date  `json:"upper"`
}

func (*DateRange) String

func (r *DateRange) String() string

type DateSpan

type DateSpan struct {
	Start *DateRange `json:"start"`
	End   *DateRange `json:"end"`
}

func (*DateSpan) String

func (s *DateSpan) String() string

type EDTFDate

type EDTFDate struct {
	Start   *DateRange `json:"start"`
	End     *DateRange `json:"end"`
	EDTF    string     `json:"edtf"`
	Level   int        `json:"level"`
	Feature string     `json:"feature"`
}

func (*EDTFDate) After added in v0.3.0

func (d *EDTFDate) After(u *EDTFDate) (bool, error)

After reports whether the EDTFDate instance `d` is after `u`.

func (*EDTFDate) Before added in v0.3.0

func (d *EDTFDate) Before(u *EDTFDate) (bool, error)

Before reports whether the EDTFDate instance `d` is after `u`.

func (*EDTFDate) Lower

func (d *EDTFDate) Lower() (*time.Time, error)

func (*EDTFDate) String

func (d *EDTFDate) String() string

func (*EDTFDate) Upper

func (d *EDTFDate) Upper() (*time.Time, error)

type InvalidError

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

func (*InvalidError) Error

func (e *InvalidError) Error() string

type NotImplementedError

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

func (*NotImplementedError) Error

func (e *NotImplementedError) Error() string

type NotSetError added in v0.2.0

type NotSetError struct {
}

func (*NotSetError) Error added in v0.2.0

func (e *NotSetError) Error() string

type Precision

type Precision uint32
const (
	NONE      Precision = 0
	ALL       Precision = 1 << iota // 2
	ANY                             // 4
	DAY                             // 8
	WEEK                            // 16
	MONTH                           // 32
	YEAR                            // 64
	DECADE                          // 128
	CENTURY                         // 256
	MILLENIUM                       // 512
)

func (*Precision) AddFlag

func (f *Precision) AddFlag(flag Precision)

func (*Precision) ClearFlag

func (f *Precision) ClearFlag(flag Precision)

func (Precision) HasFlag

func (f Precision) HasFlag(flag Precision) bool

func (*Precision) IsAnnual

func (f *Precision) IsAnnual() bool

func (*Precision) IsDaily

func (f *Precision) IsDaily() bool

func (*Precision) IsMonthly

func (f *Precision) IsMonthly() bool

func (*Precision) ToggleFlag

func (f *Precision) ToggleFlag(flag Precision)

type Timestamp added in v0.2.0

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

func NewTimestampWithTime added in v0.2.0

func NewTimestampWithTime(t *time.Time) *Timestamp

func (Timestamp) MarshalJSON added in v0.2.0

func (ts Timestamp) MarshalJSON() ([]byte, error)

func (*Timestamp) Time added in v0.2.0

func (ts *Timestamp) Time() *time.Time

func (*Timestamp) Unix added in v0.2.0

func (ts *Timestamp) Unix() int64

func (*Timestamp) UnmarshalJSON added in v0.2.0

func (ts *Timestamp) UnmarshalJSON(b []byte) error

type UnrecognizedError added in v0.2.0

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

func (*UnrecognizedError) Error added in v0.2.0

func (e *UnrecognizedError) Error() string

type UnsupportedError

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

func (*UnsupportedError) Error

func (e *UnsupportedError) Error() string

type YMD

type YMD struct {
	Year  int `json:"year"`
	Month int `json:"month"`
	Day   int `json:"day"`
}

func (*YMD) Equals

func (ymd *YMD) Equals(other_ymd *YMD) bool

func (*YMD) String

func (ymd *YMD) String() string

Directories

Path Synopsis
package calendar provides common date and calendar methods.
package calendar provides common date and calendar methods.
cmd
matches
matches is a command-line tool to read one or more EDTF strings and emit the EDTF level and feature name they match.
matches is a command-line tool to read one or more EDTF strings and emit the EDTF level and feature name they match.
parse
parse is a command-line tool to read one or more EDTF strings and return a list of JSON-encode edtf.EDTFDate objects.
parse is a command-line tool to read one or more EDTF strings and return a list of JSON-encode edtf.EDTFDate objects.
package cmp provides methods for comparing EDTF dates (typically string representations)
package cmp provides methods for comparing EDTF dates (typically string representations)
package common provide common methods across EDTF level definitions.
package common provide common methods across EDTF level definitions.
package parser provides methods for parsing and validating EDTF strings.
package parser provides methods for parsing and validating EDTF strings.
package unix provides methods for derving Unix timestamps from EDTF strings.
package unix provides methods for derving Unix timestamps from EDTF strings.

Jump to

Keyboard shortcuts

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