diff --git a/.travis.yml b/.travis.yml index fb8032e..d8b4934 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,103 @@ +# Based on the "trust" template v0.1.2 +# https://github.com/japaric/trust/tree/v0.1.2 + +dist: trusty language: rust -rust: - - stable - - beta - - nightly \ No newline at end of file +services: docker +sudo: required + +env: + global: + - CRATE_NAME=dtparse + +matrix: + include: + # Android + - env: TARGET=aarch64-linux-android DISABLE_TESTS=1 + - env: TARGET=arm-linux-androideabi DISABLE_TESTS=1 + - env: TARGET=armv7-linux-androideabi DISABLE_TESTS=1 + - env: TARGET=i686-linux-android DISABLE_TESTS=1 + - env: TARGET=x86_64-linux-android DISABLE_TESTS=1 + + # iOS + - env: TARGET=aarch64-apple-ios DISABLE_TESTS=1 + os: osx + - env: TARGET=armv7-apple-ios DISABLE_TESTS=1 + os: osx + - env: TARGET=armv7s-apple-ios DISABLE_TESTS=1 + os: osx + - env: TARGET=i386-apple-ios DISABLE_TESTS=1 + os: osx + - env: TARGET=x86_64-apple-ios DISABLE_TESTS=1 + os: osx + + # Linux + - env: TARGET=aarch64-unknown-linux-gnu + - env: TARGET=arm-unknown-linux-gnueabi + - env: TARGET=armv7-unknown-linux-gnueabihf + - env: TARGET=i686-unknown-linux-gnu + - env: TARGET=i686-unknown-linux-musl + - env: TARGET=mips-unknown-linux-gnu + - env: TARGET=mips64-unknown-linux-gnuabi64 + - env: TARGET=mips64el-unknown-linux-gnuabi64 + - env: TARGET=mipsel-unknown-linux-gnu + - env: TARGET=powerpc-unknown-linux-gnu + - env: TARGET=powerpc64-unknown-linux-gnu + - env: TARGET=powerpc64le-unknown-linux-gnu + - env: TARGET=s390x-unknown-linux-gnu DISABLE_TESTS=1 + - env: TARGET=x86_64-unknown-linux-gnu + - env: TARGET=x86_64-unknown-linux-musl + + # OSX + - env: TARGET=i686-apple-darwin + os: osx + - env: TARGET=x86_64-apple-darwin + os: osx + + # *BSD + - env: TARGET=i686-unknown-freebsd DISABLE_TESTS=1 + - env: TARGET=x86_64-unknown-freebsd DISABLE_TESTS=1 + - env: TARGET=x86_64-unknown-netbsd DISABLE_TESTS=1 + + # Windows + - env: TARGET=x86_64-pc-windows-gnu + + # Nightly and Beta + - env: TARGET=x86_64-unknown-linux-gnu + rust: nightly + - env: TARGET=x86_64-apple-darwin + os: osx + rust: nightly + - env: TARGET=x86_64-unknown-linux-gnu + rust: beta + - env: TARGET=x86_64-apple-darwin + os: osx + rust: beta + +before_install: + - set -e + - rustup self update + +install: + - sh ci/install.sh + - source ~/.cargo/env || true + +script: + - bash ci/script.sh + +after_script: set +e + +cache: cargo +before_cache: + # Travis can't cache files that are not readable by "others" + - chmod -R a+r $HOME/.cargo + +branches: + only: + # release tags + - /^v\d+\.\d+\.\d+.*$/ + - master + +notifications: + email: + on_success: never diff --git a/README.md b/README.md index c7967c7..4c00586 100644 --- a/README.md +++ b/README.md @@ -2,29 +2,63 @@ ![travisci](https://travis-ci.org/bspeice/dtparse.svg?branch=master) -A [dateutil](https://github.com/dateutil/dateutil)-compatible timestamp parser for Rust +The fully-featured "even I couldn't understand that" time parser. +Designed to take in strings and give back sensible dates and times. -## Where it stands +dtparse has its foundations in the [`dateutil`](dateutil) library for +Python, which excels at taking "interesting" strings and trying to make +sense of the dates and times they contain. A couple of quick examples +from the test cases should give some context: -The library works really well at the moment, and passes the vast majority of `dateutil`s parser -test suite. This isn't mission-critical ready, but is more than ready for hobbyist projects. +```rust +extern crate chrono; +extern crate dtparse; +use chrono::prelude::*; +use dtparse::parse; -The issues to be resolved before version 1.0: +assert_eq!( + parse("2008.12.30"), + Ok((NaiveDate::from_ymd(2008, 12, 30).and_hms(0, 0, 0), None)) +); -**Functionality**: +// It can even handle timezones! +assert_eq!( + parse("January 4, 2024; 18:30:04 +02:00"), + Ok(( + NaiveDate::from_ymd(2024, 1, 4).and_hms(18, 30, 4), + Some(FixedOffset::east(7200)) + )) +); +``` -1. ~~We don't support weekday parsing. In the Python side this is accomplished via `dateutil.relativedelta`~~ -Supported in v0.8 +And we can even handle fuzzy strings where dates/times aren't the +only content if we dig into the implementation a bit! -2. Named timezones aren't supported very well. [chrono_tz](https://github.com/chronotope/chrono-tz) -theoretically would provide support, but I'd also like some helper things available (e.g. "EST" is not a named zone in `chrono-tz`). -Explicit time zones (i.e. "00:00:00 -0300") are working as expected. +```rust +extern crate chrono; +extern crate dtparse; +use chrono::prelude::*; +use dtparse::Parser; +use std::collections::HashMap; -3. ~~"Fuzzy" and "Fuzzy with tokens" modes haven't been tested. The code should work, but I need to get the -test cases added to the auto-generation suite~~ +let mut p = Parser::default(); +assert_eq!( + p.parse( + "I first released this library on the 17th of June, 2018.", + None, None, + true /* turns on fuzzy mode */, + true /* gives us the tokens that weren't recognized */, + None, false, &HashMap::new() + ), + Ok(( + NaiveDate::from_ymd(2018, 6, 17).and_hms(0, 0, 0), + None, + Some(vec!["I first released this library on the ", + " of ", ", "].iter().map(|&s| s.into()).collect()) + )) +); +``` -**Non-functional**: This library is intended to be a direct port from Python, and thus the code -looks a lot more like Python than it does Rust. There are a ton of `TODO` comments in the code -that need cleaned up, things that could be converted to enums, etc. +Further examples can be found in the `examples` directory on international usage. -In addition, some more documentation would be incredibly helpful. It's, uh, sparse at the moment. +[dateutil]: https://github.com/dateutil/dateutil diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..a0c4f1b --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,121 @@ +# Appveyor configuration template for Rust using rustup for Rust installation +# https://github.com/starkat99/appveyor-rust + +## Operating System (VM environment) ## + +# Rust needs at least Visual Studio 2013 Appveyor OS for MSVC targets. +os: Visual Studio 2017 + +## Build Matrix ## + +# This configuration will setup a build for each channel & target combination (12 windows +# combinations in all). +# +# There are 3 channels: stable, beta, and nightly. +# +# Alternatively, the full version may be specified for the channel to build using that specific +# version (e.g. channel: 1.5.0) +# +# The values for target are the set of windows Rust build targets. Each value is of the form +# +# ARCH-pc-windows-TOOLCHAIN +# +# Where ARCH is the target architecture, either x86_64 or i686, and TOOLCHAIN is the linker +# toolchain to use, either msvc or gnu. See https://www.rust-lang.org/downloads.html#win-foot for +# a description of the toolchain differences. +# See https://github.com/rust-lang-nursery/rustup.rs/#toolchain-specification for description of +# toolchains and host triples. +# +# Comment out channel/target combos you do not wish to build in CI. +# +# You may use the `cargoflags` and `RUSTFLAGS` variables to set additional flags for cargo commands +# and rustc, respectively. For instance, you can uncomment the cargoflags lines in the nightly +# channels to enable unstable features when building for nightly. Or you could add additional +# matrix entries to test different combinations of features. +environment: + matrix: + +### MSVC Toolchains ### + + # Stable 64-bit MSVC + - channel: stable + target: x86_64-pc-windows-msvc + # Stable 32-bit MSVC + - channel: stable + target: i686-pc-windows-msvc + # Beta 64-bit MSVC + - channel: beta + target: x86_64-pc-windows-msvc + # Beta 32-bit MSVC + - channel: beta + target: i686-pc-windows-msvc + # Nightly 64-bit MSVC + - channel: nightly + target: x86_64-pc-windows-msvc + #cargoflags: --features "unstable" + # Nightly 32-bit MSVC + - channel: nightly + target: i686-pc-windows-msvc + #cargoflags: --features "unstable" + +### GNU Toolchains ### + + # Stable 64-bit GNU + - channel: stable + target: x86_64-pc-windows-gnu + # Stable 32-bit GNU + - channel: stable + target: i686-pc-windows-gnu + # Beta 64-bit GNU + - channel: beta + target: x86_64-pc-windows-gnu + # Beta 32-bit GNU + - channel: beta + target: i686-pc-windows-gnu + # Nightly 64-bit GNU + - channel: nightly + target: x86_64-pc-windows-gnu + #cargoflags: --features "unstable" + # Nightly 32-bit GNU + - channel: nightly + target: i686-pc-windows-gnu + #cargoflags: --features "unstable" + +### Allowed failures ### + +# See Appveyor documentation for specific details. In short, place any channel or targets you wish +# to allow build failures on (usually nightly at least is a wise choice). This will prevent a build +# or test failure in the matching channels/targets from failing the entire build. +matrix: + allow_failures: + - channel: nightly + +# If you only care about stable channel build failures, uncomment the following line: + #- channel: beta + +## Install Script ## + +# This is the most important part of the Appveyor configuration. This installs the version of Rust +# specified by the 'channel' and 'target' environment variables from the build matrix. This uses +# rustup to install Rust. +# +# For simple configurations, instead of using the build matrix, you can simply set the +# default-toolchain and default-host manually here. +install: + - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe + - rustup-init -yv --default-toolchain %channel% --default-host %target% + - set PATH=%PATH%;%USERPROFILE%\.cargo\bin + - rustc -vV + - cargo -vV + +## Build Script ## + +# 'cargo test' takes care of building for us, so disable Appveyor's build stage. This prevents +# the "directory does not contain a project or solution file" error. +build: false + +# Uses 'cargo test' to run tests and build. Alternatively, the project may call compiled programs +#directly or perform other testing commands. Rust will automatically be placed in the PATH +# environment variable. +test_script: +- cargo test --verbose %cargoflags% \ No newline at end of file diff --git a/ci/install.sh b/ci/install.sh new file mode 100755 index 0000000..80e18e4 --- /dev/null +++ b/ci/install.sh @@ -0,0 +1,47 @@ +set -ex + +main() { + local target= + if [ $TRAVIS_OS_NAME = linux ]; then + target=x86_64-unknown-linux-musl + sort=sort + else + target=x86_64-apple-darwin + sort=gsort # for `sort --sort-version`, from brew's coreutils. + fi + + # Builds for iOS are done on OSX, but require the specific target to be + # installed. + case $TARGET in + aarch64-apple-ios) + rustup target install aarch64-apple-ios + ;; + armv7-apple-ios) + rustup target install armv7-apple-ios + ;; + armv7s-apple-ios) + rustup target install armv7s-apple-ios + ;; + i386-apple-ios) + rustup target install i386-apple-ios + ;; + x86_64-apple-ios) + rustup target install x86_64-apple-ios + ;; + esac + + # This fetches latest stable release + local tag=$(git ls-remote --tags --refs --exit-code https://github.com/japaric/cross \ + | cut -d/ -f3 \ + | grep -E '^v[0.1.0-9.]+$' \ + | $sort --version-sort \ + | tail -n1) + curl -LSfs https://japaric.github.io/trust/install.sh | \ + sh -s -- \ + --force \ + --git japaric/cross \ + --tag $tag \ + --target $target +} + +main diff --git a/ci/script.sh b/ci/script.sh new file mode 100644 index 0000000..d90650e --- /dev/null +++ b/ci/script.sh @@ -0,0 +1,23 @@ +# This script takes care of testing your crate + +set -ex + +main() { + cross build --target $TARGET + cross build --target $TARGET --release + + if [ ! -z $DISABLE_TESTS ]; then + return + fi + + cross test --target $TARGET + cross test --target $TARGET --release + + cross run --target $TARGET + cross run --target $TARGET --release +} + +# we don't run the "test phase" when doing deploys +if [ -z $TRAVIS_TAG ]; then + main +fi \ No newline at end of file