Skip to content

Releases: kmoneil/dateparsa.zig

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 30 Oct 15:31

Layouts from a format string. Every input parses to what it did in 0.4.2.

Added

  • Layout.fromFormatString(dialect, format, opts), the inverse of
    formatString: a layout from a strftime, Go or Java format string, for a
    column whose format is known, so that no value is detected. The order is
    the format's, so %d/%m/%Y gives a reusable layout where one detected
    from 13/02/2024 is decided per value. Each dialect reads as its own
    parser does, within what a layout holds: a one-or-two-digit field takes
    either, %f one to nine digits, %z Z or either offset form, and a
    month or weekday name any month or weekday in English and the options'
    locales. error.Unsupported for a field no layout reads,
    error.InvalidFormat for a string that is no date format, and
    error.NoBaseTime for one with no year and no base time. Through C as
    dateparsa_layout_from_format and through Python as
    Layout.from_format. Two fuzz targets hold it: a layout's format string
    read back reads the value it was spelled from to the same time, and
    agrees with the layout wherever both read; and a layout from any format
    string spells formats that read back to the same time. (#27)

Changed

  • A reused layout whose fields all have fixed widths (ISO 8601, RFC 3339,
    SQL, compact dates) reads a value in about 0.9 of the time it did: an ISO
    date-time in 9.7 ns where it took 10.3, an ISO date in 6.8 where it took
    7.8, on an M5 Max. The fixed-slot path is inlined into execute by hand.
  • formatString spells from any value the layout reads, not only the one
    it was detected from at the same widths: a layout from 1/2/2024 spells
    11/12/2024 as %m/%d/%Y where it gave error.NotDetectedFrom. Python's
    Layout.format_string takes the value as value=.
  • formatString writes text between two fields as one run, so Java quotes
    it once; refuses a NUL, which no C format string holds; spells a literal
    T after a one-or-two-digit day rather than refusing it; spells a
    weekday only in English and the locales the layout reads, and only as a
    whole word, as a format string reads one; and refuses any format
    fromFormatString would not read back, such as one with more runs of
    text than a layout has fields.

v0.4.2

Choose a tag to compare

@github-actions github-actions released this 29 Oct 23:30

Faster email and HTTP dates. Every input parses to what it did in 0.4.1.

Changed

  • An email or HTTP date ("Fri, 15 Mar 2024 10:30:00 +0000", "Sun, 06 Nov
    1994 08:49:37 GMT") parses in about a quarter of the time it did, whatever
    locales are on: 79 ns where it took 324, on an M5 Max. The textual
    detector they went through finds a month name anywhere in any input; the
    shapes email and HTTP write now have their fields and a layout for each
    month built at comptime, from the detector's own answer, and an input of
    one of them is checked against its shape instead. A fuzz target holds the
    two to the same answer.

v0.4.1

Choose a tag to compare

@github-actions github-actions released this 29 Oct 22:12

Faster detection. Every input parses to what it did in 0.4.0.

Changed

  • A first parse of a format the signature trie knows takes about 0.6 of
    the time it did, and so does everything built on parse (Parser on a
    value its cached layout cannot read, the C interface, Python, the
    command): detection hands the format back by its table index instead of
    copying its 168-byte definition out of the trie and twice more on the
    way up, and looks for a CJK date only when 年 is the fifth byte. Against
    the Go library's benchmarks, ISO 8601, RFC 3339, SQL and compact forms
    now take 0.54 to 0.66 of Go's time, where they took 0.88 to 1.05.

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 29 Oct 21:08

A column in one call, from C and from Python. Every input parses to what it
did in 0.3.3.

Added

  • dateparsa_parse_column: every value in a buffer, each ending at a
    separator byte, parsed down one parser in one call, into an array of the
    new dateparsa_value (the time, Unix seconds, kind, whether it was a
    guess, and a status saying why a value did not parse). It allocates
    nothing; every array is the caller's. For a language where a call into C
    costs more than a parse does.
  • dateparsa.parse_column(values, **options) in Python, on top of it: one
    call into the library for the whole column, with None read as a value
    that does not parse. Down 10,000 RFC 3339 values on Python 3.13
    (docs/PERF.md) it takes 169 ns a value to datetimes, where a Parser
    called once a value takes 1.12 µs, and 32.9 ns into numpy, where pandas
    working out the format takes 78.2. What it returns gives datetimes(),
    times(), failed and ambiguous, and datetime64() for a numpy array
    pandas takes, NaT where a value did not parse; numpy is not a
    dependency.
  • A fuzz target: the column call, on any bytes split at any separator,
    answers for each value what a Parser answers parsing them in turn.

v0.3.3

Choose a tag to compare

@github-actions github-actions released this 29 Oct 19:48

A faster Python package. No library code changed, and every input parses
to what it did in 0.3.2.

Changed

  • The Python package spends far less of each call in Python: parse
    takes a quarter to a third of the time it did (3.5 µs to 1.1 on Python
    3.13, in docs/PERF.md), Parser.parse about half, and Layout.parse
    and detect a half to two thirds, with the same answers. From Python,
    parse is now faster than strptime given the format. The
    default options go to the library as NULL and other options are built
    once and shared; a result's fields are read in one struct unpack, its
    Time and Result built without the dataclass __init__, and its
    layout is a view of the result rather than a copy. A failed call is
    run again with diagnostics, for its message, so a parse that succeeds
    never pays for them.

v0.3.2

Choose a tag to compare

@github-actions github-actions released this 29 Oct 18:51

Benchmarks against other parsers. No library code changed, and every input
parses to what it did in 0.3.1.

Added

  • tools/bench_others.sh: dateparsa against other date parsers on one
    machine. In Zig, against zeit. In Rust, through the C interface, against
    chrono, jiff, time, speedate and dateparser, with heap allocations per
    parse counted. In Python, through the package, against fromisoformat,
    strptime, ciso8601, dateutil, dateparser and pandas, one value at a time
    and down a column. Every parser's answer is checked before it is timed,
    and each harness pins the versions it compares against. docs/PERF.md
    has the first run and what it shows, including what the shared library
    imports: on macOS, bzero, memcpy and memset, and nothing that could
    ask the system for memory.

v0.3.1

Choose a tag to compare

@github-actions github-actions released this 29 Oct 12:46

The dateparsa command, prebuilt. No library code changed, and every input
parses to what it did in 0.3.0.

Added

  • The dateparsa command. dateparsa detect reports how a column is
    written: the formats its values take, each spelled for strftime, Go and
    Java, the order its numeric dates are in and the value that settled it, the
    values that needed the column's order, and the values it could not read, by
    line. dateparsa normalize writes the input back with the column as RFC
    3339, changing no other byte, and refuses to guess an order nothing in the
    column settles. CSV with --col N or --col NAME (quoted fields, any
    one-byte separator), or one value a line, from a file or standard input;
    --order, --base, --tz, --utc, --locale and detect --json. The
    release archives carry it in bin/ for every platform, and each release
    runs it on Linux, macOS and Windows before publishing.

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 28 Oct 20:39

A column's date order, format strings for other tools, and a Python
package. All of it is new API: nothing that existed changed, and every input
parses to what it did in 0.2.1.

Added

  • detectColumn and Column: which order a column writes its numeric dates
    in, month, day or year first, from all of its values where one value
    cannot say. One 13/02/2024 settles day first for the whole column, and
    two-digit years narrow it together. The report gives the order, the value
    that settled it, any values that contradict it, and the Options that read
    the column in it. Column takes values one at a time and allocates
    nothing. In C: dateparsa_column_init, dateparsa_column_add and
    dateparsa_column_summarize.
  • Layout.dateOrder(): the order a numeric layout reads year, month and day
    in.
  • Layout.formatString(dialect, detected_from, writer): a detected format as
    another tool's format string, in strftime (C, Python, pandas, Ruby), Go or
    Java (also Kotlin and Spark) form, such as %d/%m/%Y %H:%M. A field a
    dialect cannot spell is error.Unsupported, never a string that reads
    something else. Every example in the format table is checked in Python, Go
    and Java by tools/format_check.sh. In C: dateparsa_format_string and
    the new status DATEPARSA_UNSUPPORTED.
  • A Python package, pip install dateparsa: wheels for Linux (glibc and musl),
    macOS 13 and later, and Windows, on x86_64 and arm64, for Python 3.9 and
    later, wrapping the release libraries with ctypes. parse, detect,
    Parser, Layout (with format_string), detect_column and Column,
    with options as keyword arguments, results as datetimes, and NoMatch,
    Ambiguous and NoBaseTime as ValueErrors. Every release installs each
    wheel on its platform and runs the tests before publishing to PyPI as a
    trusted publisher.

v0.2.1

Choose a tag to compare

@github-actions github-actions released this 28 Oct 18:05

The C library, prebuilt. No library code changed, and every input parses to
what it did in 0.2.0.

Added

  • Prebuilt libdateparsa on every release, for Linux, macOS 13 and later, and
    Windows, each on x86_64 and arm64: one archive per platform with the static
    and the shared library, the header and the licences, plus SHA256SUMS and
    build provenance. Before a release publishes them, each runner OS links the
    C tests against its own platform's archive with the compiler it already
    has, and runs them.

v0.2.0

Choose a tag to compare

@github-actions github-actions released this 28 Oct 17:03

The C interface. Nothing a Zig caller sees changed, and every input parses to
what it did in 0.1.0.

Added

  • A C interface, for every language that can call C. zig build lib builds
    libdateparsa, static or with -Dlinkage=dynamic shared, and installs
    include/dateparsa.h. It covers parse, detect, layout reuse, Parser,
    strict mode and its diagnostics, locales by bit or by BCP 47 tag, RFC 3339
    output and Unix seconds, and allocates nothing: every struct is the
    caller's. What a C caller passes in is checked, not trusted: a base time
    that is no date, an offset of a day or more, a base year more than
    999,999,999 from year 0, a locale bit the build left out, a NULL, or a
    layout or parser the library never filled in is
    DATEPARSA_INVALID_ARGUMENT.