Compare commits

...

16 Commits

Author SHA1 Message Date
Abraham Toriz 08ff8254d1
derive some defaults to make clippy happy 2023-03-14 16:04:57 -05:00
Abraham Toriz 22d16ff5ba separate cli definition into its own file 2023-03-11 19:29:09 -06:00
Abraham Toriz 530dd8dc15
simpler way of specifying no command 2023-02-13 19:58:13 -06:00
Abraham Toriz 858302839c
upgrade clap to v3 2023-02-13 18:17:47 -06:00
Abraham Toriz 56393636c9
change wording in readme 2023-02-03 12:17:09 -06:00
Abraham Toriz 518fe26c82
fix changelog 2022-11-26 21:16:46 -06:00
Abraham Toriz dd6b9f9a8d
Redefined CI and smaller features 2022-11-26 21:01:52 -06:00
Abraham Toriz 6afb517535
changelog and docs for 1.6 2022-11-26 21:00:11 -06:00
Abraham Toriz 3f83485769
another two paths were incorrect 2022-11-26 19:56:51 -06:00
Abraham Toriz 5d8d80fcfd
condense podman command lines in scripts 2022-11-26 19:43:38 -06:00
Abraham Toriz 4d1e3537df
fix package name again in archlinux-bin 2022-11-26 19:26:40 -06:00
Abraham Toriz a8990533bc
changelog for new release 2022-11-26 18:57:12 -06:00
Abraham Toriz 9cc6a88de6
a task for later 2022-11-26 18:54:26 -06:00
Abraham Toriz 5ae5e32cfb
fix variable names in CI 2022-11-26 18:54:17 -06:00
Abraham Toriz d56ef65f73
add a (un)install script to package 2022-11-26 18:52:41 -06:00
Abraham Toriz c9f5782f59
fix path to artifacts in CI 2022-11-26 18:23:55 -06:00
40 changed files with 886 additions and 623 deletions

View File

@ -71,10 +71,10 @@ upload:
when: never
- if: $CI_COMMIT_TAG =~ /^v*/
script:
- 'curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file artifacts/tiempo-${CI_COMMIT_TAG:1}-x86_64.tar.gz ${PACKAGE_REGISTRY_URL}/tiempo-${CI_COMMIT_TAG:1}-x86_64.tar.gz'
- 'curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file artifacts/tiempo-${CI_COMMIT_TAG:1}-x86_64.tar.gz.sum ${PACKAGE_REGISTRY_URL}/tiempo-${CI_COMMIT_TAG:1}-x86_64.tar.gz.sum'
- 'curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file artifacts/tiempo_${CI_COMMIT_TAG:1}_amd64.deb ${PACKAGE_REGISTRY_URL}/tiempo_${CI_COMMIT_TAG:1}_amd64.deb'
- 'curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file artifacts/tiempo_${CI_COMMIT_TAG:1}_amd64.deb.sum ${PACKAGE_REGISTRY_URL}/tiempo_${CI_COMMIT_TAG:1}_amd64.deb.sum'
- 'curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file artifacts/tiempo-${CI_COMMIT_TAG}-x86_64.tar.gz ${PACKAGE_REGISTRY_URL}/tiempo-${CI_COMMIT_TAG}-x86_64.tar.gz'
- 'curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file artifacts/tiempo-${CI_COMMIT_TAG}-x86_64.tar.gz.sum ${PACKAGE_REGISTRY_URL}/tiempo-${CI_COMMIT_TAG}-x86_64.tar.gz.sum'
- 'curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file artifacts/tiempo_${CI_COMMIT_TAG}_amd64.deb ${PACKAGE_REGISTRY_URL}/tiempo_${CI_COMMIT_TAG}_amd64.deb'
- 'curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file artifacts/tiempo_${CI_COMMIT_TAG}_amd64.deb.sum ${PACKAGE_REGISTRY_URL}/tiempo_${CI_COMMIT_TAG}_amd64.deb.sum'
release:
stage: release
@ -114,13 +114,13 @@ deploy:arch-bin:
- git config --global user.name "$COMMITER_NAME"
- git config --global user.email "$COMMITER_EMAIL"
# Clone the repo
- git clone $BIN_REPO_URL $PROJECT_NAME-bin
- git clone $BIN_REPO_URL tiempo-bin
# generate the PKGBUILD in the current directory
- scripts/release-aur-bin.sh
- mv PKGBUILD $PROJECT_NAME-bin/
- mv .SRCINFO $PROJECT_NAME-bin/
- mv PKGBUILD tiempo-bin/
- mv .SRCINFO tiempo-bin/
# commit
- cd $PROJECT_NAME-bin
- cd tiempo-bin
- git add .
- git commit -m "Release version $CI_COMMIT_TAG"
- git push
@ -142,13 +142,13 @@ deploy:arch-git:
- git config --global user.name "$COMMITER_NAME"
- git config --global user.email "$COMMITER_EMAIL"
# clone the repo
- git clone $GIT_REPO_URL $PROJECT_NAME-git
- git clone $GIT_REPO_URL tiempo-git
# finally run the script
- scripts/release-aur-git.sh
- mv PKGBUILD $PROJECT_NAME-bin/
- mv .SRCINFO $PROJECT_NAME-bin/
- mv PKGBUILD tiempo-git/
- mv .SRCINFO tiempo-git/
# and commit
- cd $PROJECT_NAME-bin
- cd tiempo-git
- git add .
- git commit -m "Release version $VERSION"
- git push

View File

@ -1,9 +1,10 @@
# Changes
## next
## 1.6
- `t now` displays a nicer message if no entries are running.
- `chart` formatter now shows the sheet name(s) that are being displayed.
- any-linux package now includes install script.
## 1.5.3
@ -13,7 +14,7 @@
- binary package structure changed
## 1.5
r
- First release to include the man page. Documentation is now published in
https://tiempo.categulario.xyz

555
Cargo.lock generated
View File

@ -4,9 +4,9 @@ version = 3
[[package]]
name = "ahash"
version = "0.7.4"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
"getrandom",
"once_cell",
@ -15,20 +15,20 @@ dependencies = [
[[package]]
name = "aho-corasick"
version = "0.7.18"
version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
dependencies = [
"memchr",
]
[[package]]
name = "ansi_term"
version = "0.11.0"
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"winapi",
"libc",
]
[[package]]
@ -68,15 +68,15 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.2.1"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bstr"
version = "0.2.16"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279"
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
dependencies = [
"lazy_static",
"memchr",
@ -85,10 +85,16 @@ dependencies = [
]
[[package]]
name = "cc"
version = "1.0.69"
name = "bumpalo"
version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2"
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]]
name = "cc"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cfg-if"
@ -98,31 +104,43 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.19"
version = "0.4.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
dependencies = [
"libc",
"iana-time-zone",
"js-sys",
"num-integer",
"num-traits",
"serde",
"time",
"wasm-bindgen",
"winapi",
]
[[package]]
name = "clap"
version = "2.33.3"
version = "3.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5"
dependencies = [
"ansi_term 0.11.0",
"atty",
"bitflags",
"clap_lex",
"indexmap",
"once_cell",
"strsim",
"textwrap 0.11.0",
"unicode-width",
"vec_map",
"termcolor",
"textwrap 0.16.0",
]
[[package]]
name = "clap_lex"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
dependencies = [
"os_str_bytes",
]
[[package]]
@ -134,6 +152,22 @@ dependencies = [
"bitflags",
]
[[package]]
name = "codespan-reporting"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
dependencies = [
"termcolor",
"unicode-width",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "csv"
version = "1.1.6"
@ -142,7 +176,7 @@ checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
dependencies = [
"bstr",
"csv-core",
"itoa 0.4.7",
"itoa 0.4.8",
"ryu",
"serde",
]
@ -158,19 +192,63 @@ dependencies = [
[[package]]
name = "ctor"
version = "0.1.20"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d"
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "diff"
version = "0.1.12"
name = "cxx"
version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
checksum = "90d59d9acd2a682b4e40605a242f6670eaa58c5957471cbf85e8aa6a0b97a5e8"
dependencies = [
"cc",
"cxxbridge-flags",
"cxxbridge-macro",
"link-cplusplus",
]
[[package]]
name = "cxx-build"
version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebfa40bda659dd5c864e65f4c9a2b0aff19bea56b017b9b77c73d3766a453a38"
dependencies = [
"cc",
"codespan-reporting",
"once_cell",
"proc-macro2",
"quote",
"scratch",
"syn",
]
[[package]]
name = "cxxbridge-flags"
version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "457ce6757c5c70dc6ecdbda6925b958aae7f959bda7d8fb9bde889e34a09dc03"
[[package]]
name = "cxxbridge-macro"
version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebf883b7aacd7b2aeb2a7b338648ee19f57c140d4ee8e52c68979c6b2f7f2263"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "diff"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "directories"
@ -183,9 +261,9 @@ dependencies = [
[[package]]
name = "dirs-sys"
version = "0.3.6"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
dependencies = [
"libc",
"redox_users",
@ -194,9 +272,9 @@ dependencies = [
[[package]]
name = "either"
version = "1.6.1"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "fallible-iterator"
@ -210,6 +288,15 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]]
name = "fastrand"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
dependencies = [
"instant",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
@ -218,13 +305,13 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "getrandom"
version = "0.2.3"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc",
"wasi",
"wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
@ -238,9 +325,9 @@ dependencies = [
[[package]]
name = "hashlink"
version = "0.8.0"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d452c155cb93fecdfb02a73dd57b5d8e442c2063bd7aac72f1bc5e4263a43086"
checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa"
dependencies = [
"hashbrown",
]
@ -266,15 +353,48 @@ dependencies = [
]
[[package]]
name = "indexmap"
version = "1.9.1"
name = "iana-time-zone"
version = "0.1.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"winapi",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
dependencies = [
"cxx",
"cxx-build",
]
[[package]]
name = "indexmap"
version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [
"autocfg 1.1.0",
"hashbrown",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "isolang"
version = "1.0.0"
@ -287,24 +407,33 @@ dependencies = [
[[package]]
name = "itertools"
version = "0.10.1"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "0.4.7"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "itoa"
version = "1.0.3"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "js-sys"
version = "0.3.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
@ -314,21 +443,39 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.98"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "libsqlite3-sys"
version = "0.25.1"
version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f0455f2c1bc9a7caa792907026e469c1d91761fb0ea37cbb16427c77280cf35"
checksum = "29f835d03d717946d28b1d1ed632eb6f0e24a299388ee623d0c23118d3e8a7fa"
dependencies = [
"cc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "link-cplusplus"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
dependencies = [
"cc",
]
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "match_cfg"
version = "0.1.0"
@ -337,15 +484,15 @@ checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
[[package]]
name = "memchr"
version = "2.4.0"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "num-integer"
version = "0.1.44"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg 1.1.0",
"num-traits",
@ -353,24 +500,30 @@ dependencies = [
[[package]]
name = "num-traits"
version = "0.2.14"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg 1.1.0",
]
[[package]]
name = "once_cell"
version = "1.8.0"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]]
name = "os_str_bytes"
version = "6.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
[[package]]
name = "output_vt100"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
dependencies = [
"winapi",
]
@ -401,7 +554,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
dependencies = [
"phf_shared",
"rand 0.6.5",
"rand",
]
[[package]]
@ -415,42 +568,36 @@ dependencies = [
[[package]]
name = "pkg-config"
version = "0.3.19"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "ppv-lite86"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "pretty_assertions"
version = "1.2.1"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c89f989ac94207d048d92db058e4f6ec7342b0971fc58d1271ca148b799b3563"
checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755"
dependencies = [
"ansi_term 0.12.1",
"ctor",
"diff",
"output_vt100",
"yansi",
]
[[package]]
name = "proc-macro2"
version = "1.0.43"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.9"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
@ -463,9 +610,9 @@ checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
dependencies = [
"autocfg 0.1.8",
"libc",
"rand_chacha 0.1.1",
"rand_chacha",
"rand_core 0.4.2",
"rand_hc 0.1.0",
"rand_hc",
"rand_isaac",
"rand_jitter",
"rand_os",
@ -474,18 +621,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "rand"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_core 0.6.3",
"rand_hc 0.3.1",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
@ -496,16 +631,6 @@ dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core 0.6.3",
]
[[package]]
name = "rand_core"
version = "0.3.1"
@ -521,15 +646,6 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rand_core"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.1.0"
@ -539,15 +655,6 @@ dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_hc"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
dependencies = [
"rand_core 0.6.3",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
@ -612,28 +719,29 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.2.9"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
version = "0.4.0"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom",
"redox_syscall",
"thiserror",
]
[[package]]
name = "regex"
version = "1.5.4"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
dependencies = [
"aho-corasick",
"memchr",
@ -648,9 +756,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-syntax"
version = "0.6.25"
version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "remove_dir_all"
@ -678,24 +786,30 @@ dependencies = [
[[package]]
name = "ryu"
version = "1.0.5"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[package]]
name = "scratch"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2"
[[package]]
name = "serde"
version = "1.0.144"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.144"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
dependencies = [
"proc-macro2",
"quote",
@ -704,23 +818,23 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.65"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28c5e91e4240b46c4c19219d6cc84784444326131a4210f496f948d5cc827a29"
checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76"
dependencies = [
"itoa 0.4.7",
"itoa 1.0.5",
"ryu",
"serde",
]
[[package]]
name = "serde_yaml"
version = "0.9.11"
version = "0.9.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89f31df3f50926cdf2855da5fd8812295c34752cb20438dae42a67f79e021ac3"
checksum = "8fb06d4b6cdaef0e0c51fa881acb721bed3c924cfaa71d9c94a3b771dfdf6567"
dependencies = [
"indexmap",
"itoa 1.0.3",
"itoa 1.0.5",
"ryu",
"serde",
"unsafe-libyaml",
@ -734,9 +848,9 @@ checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
[[package]]
name = "smallvec"
version = "1.6.1"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "smawk"
@ -746,15 +860,15 @@ checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043"
[[package]]
name = "strsim"
version = "0.8.0"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.99"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
@ -763,25 +877,25 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.2.0"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
dependencies = [
"cfg-if",
"fastrand",
"libc",
"rand 0.8.4",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[package]]
name = "textwrap"
version = "0.11.0"
name = "termcolor"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
dependencies = [
"unicode-width",
"winapi-util",
]
[[package]]
@ -796,19 +910,25 @@ dependencies = [
]
[[package]]
name = "thiserror"
version = "1.0.26"
name = "textwrap"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2"
checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
[[package]]
name = "thiserror"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.26"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745"
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
dependencies = [
"proc-macro2",
"quote",
@ -817,9 +937,9 @@ dependencies = [
[[package]]
name = "tiempo"
version = "1.5.4"
version = "1.6.0"
dependencies = [
"ansi_term 0.12.1",
"ansi_term",
"atty",
"chrono",
"clap",
@ -843,11 +963,12 @@ dependencies = [
[[package]]
name = "time"
version = "0.1.43"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
dependencies = [
"libc",
"wasi 0.10.0+wasi-snapshot-preview1",
"winapi",
]
@ -863,39 +984,40 @@ dependencies = [
[[package]]
name = "toml"
version = "0.5.8"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
dependencies = [
"serde",
]
[[package]]
name = "unicode-ident"
version = "1.0.3"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-linebreak"
version = "0.1.2"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a52dcaab0c48d931f7cc8ef826fa51690a08e1ea55117ef26f89864f532383f"
checksum = "c5faade31a542b8b35855fff6e8def199853b2da8da256da52f52f1316ee3137"
dependencies = [
"hashbrown",
"regex",
]
[[package]]
name = "unicode-width"
version = "0.1.8"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "unsafe-libyaml"
version = "0.2.2"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "931179334a56395bcf64ba5e0ff56781381c1a5832178280c7d7f91d1679aeb0"
checksum = "bc7ed8ba44ca06be78ea1ad2c3682a43349126c8818054231ee6f4748012aed2"
[[package]]
name = "vcpkg"
@ -903,23 +1025,77 @@ version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.3"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
[[package]]
name = "winapi"
@ -937,8 +1113,23 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "yansi"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"

View File

@ -1,6 +1,6 @@
[[bin]]
name = "t"
path = "src/main.rs"
path = "src/bin/t.rs"
[package]
name = "tiempo"
@ -11,10 +11,10 @@ description = "A command line time tracker"
license = "GPL-3.0"
documentation = "https://tiempo.categulario.xyz"
homepage = "https://gitlab.com/categulario/tiempo-rs"
version = "1.5.4"
version = "1.6.0"
default-run = "t"
[dependencies]
clap = "2"
thiserror = "1"
directories = "3"
serde_yaml = "0.9"
@ -31,6 +31,10 @@ hostname = "0.3"
atty = "0.2"
timeago = "0.3"
[dependencies.clap]
version = "3"
features = ["cargo"]
[dependencies.chrono]
version = "0.4"
features = ["serde"]

View File

@ -7,20 +7,19 @@ tracking application. [Read the fine manual](https://tiempo.categulario.xyz).
### For Archlinux (and derivatives) users
There are a binary and a source package in the AUR:
There are both binary and source packages in the AUR:
* [tiempo-bin](https://aur.archlinux.org/packages/tiempo-bin)
* [tiempo-git](https://aur.archlinux.org/packages/tiempo-git)
### For every other linux users
### For all other linux users
Go to [gitlab releases page](https://gitlab.com/categulario/tiempo-rs/-/releases)
and grab the latest binary for your linux. There is a `.deb` file for Debian and
Ubuntu as well as a binary for any `x86_64` Linux.
In the case of the tar archive you just need to recursively copy its contents
into `/usr` for it to work. It already has the directory structure needed for
the binary, man page and completions to work.
In the case of the tar archive you just need to run the included `install.sh`
script.
### For Rust developers
@ -121,13 +120,13 @@ Or build it yourself from this repo:
Then build the artifacts:
podman run -it --rm -w /app -v ./:/app -v tiempo_cargo_index:/usr/local/cargo/registry -e CI_COMMIT_TAG=v1.6rc8 tiempo-build-env ./scripts/build.sh
./scripts/podman-build.sh
To build the archlinux PKGBUILDs (depends on the artifacts folder created by the
previous command):
podman run -it --rm -w /app -v ./:/app:rw -e CI_COMMIT_TAG=v1.6rc8 -e CI_PROJECT_ID=27545092 --uidmap 1000:0:1 --uidmap 0:1:1000 categulario/makepkg ./scripts/release-aur-bin.sh
podman run -it --rm -w /app -v ./:/app:rw -e CI_COMMIT_TAG=v1.6rc8 --uidmap 1000:0:1 --uidmap 0:1:1000 categulario/makepkg ./scripts/release-aur-git.sh
./scripts/podman-build-aur-bin.sh
./scripts/podman-build-aur-git.sh
Both of the previous commands produce PKGBUILDs in the current directory so if
you run both sequentially you'll lose the PKGBUILD of the first command.
@ -144,12 +143,13 @@ for and whose design I took as reference, keeping compatibility when possible.
* fix the pipeline because it's broken. The last release and its artifacts are
wrong.
* add ain install/uninstall script to the any-linux package.
* add an install/uninstall script to the any-linux package.
* finish the `summary` formatter.
* match formatters by prefix (so there's no need to type all of its name if the
prefix is unambiguous).
* let resume --interactive receive a string as the text for a new entry.
* add a command that opens the doc in the browser just like fish
* compile a package for windows in CI
## Release checklist

View File

@ -960,6 +960,8 @@ chart
Week 19.3/20.0
Timesheet: default
This formatter comes with a few settings. See :ref:`formatters` for more.
text

View File

@ -16,17 +16,20 @@ cargo test
cargo build --locked --release
# move binary
install -m 755 -D target/release/t build/bin/t
install -Dm755 target/release/t build/bin/t
# move documentation
install -m 644 -D CHANGELOG.md build/share/doc/tiempo/CHANGELOG.md
install -m 644 -D README.md build/share/doc/tiempo/README.md
install -m 644 -D LICENSE build/share/doc/tiempo/LICENSE
install -Dm644 CHANGELOG.md build/share/doc/tiempo/CHANGELOG.md
install -Dm644 README.md build/share/doc/tiempo/README.md
install -Dm644 LICENSE build/share/doc/tiempo/LICENSE
# move man page
install -m 644 -D docs/build/man/tiempo.1.gz build/share/man/man1/tiempo.1.gz
install -Dm644 docs/build/man/tiempo.1.gz build/share/man/man1/tiempo.1.gz
# move completions
install -m 644 -D completions/bash/t build/share/bash-completion/completions/t
install -m 644 -D completions/fish/t.fish build/share/fish/vendor_completions.d/t.fish
install -m 644 -D completions/zsh/_t build/share/zsh/site-functions/_t
install -Dm644 completions/bash/t build/share/bash-completion/completions/t
install -Dm644 completions/fish/t.fish build/share/fish/vendor_completions.d/t.fish
install -Dm644 completions/zsh/_t build/share/zsh/site-functions/_t
# move install scripts
install -Dm755 scripts/install.sh build/install.sh
install -Dm755 scripts/uninstall.sh build/uninstall.sh
# compress the tar file
tar -cvzf tiempo-${CI_COMMIT_TAG}-x86_64.tar.gz build/

13
scripts/install.sh Normal file
View File

@ -0,0 +1,13 @@
#!/bin/bash
__dir=$(dirname $(realpath $0))
prefix=${1:-/usr}
install -Dm755 $__dir/bin/t $prefix/bin/t
install -Dm644 $__dir/share/fish/vendor_completions.d/t.fish $prefix/share/fish/vendor_completions.d/t.fish
install -Dm644 $__dir/share/doc/tiempo/README.md $prefix/share/doc/tiempo/README.md
install -Dm644 $__dir/share/doc/tiempo/CHANGELOG.md $prefix/share/doc/tiempo/CHANGELOG.md
install -Dm644 $__dir/share/doc/tiempo/LICENSE $prefix/share/doc/tiempo/LICENSE
install -Dm644 $__dir/share/bash-completion/completions/t $prefix/share/bash-completion/completions/t
install -Dm644 $__dir/share/zsh/site-functions/_t $prefix/share/zsh/site-functions/_t
install -Dm644 $__dir/share/man/man1/tiempo.1.gz $prefix/share/man/man1/tiempo.1.gz

14
scripts/podman-build-aur-bin.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/bash
if [[ -z $1 ]]; then
echo "please pass a tag as first argument. Something like v1.6.0"
exit 1
fi
podman run -it --rm \
--workdir /app \
--volume ./:/app \
--env CI_COMMIT_TAG=$1 \
--env CI_PROJECT_ID=27545092 \
--uidmap 1000:0:1 --uidmap 0:1:1000 \
categulario/makepkg ./scripts/release-aur-bin.sh

13
scripts/podman-build-aur-git.sh Executable file
View File

@ -0,0 +1,13 @@
#!/bin/bash
if [[ -z $1 ]]; then
echo "please pass a tag as first argument. Something like v1.6.0"
exit 1
fi
podman run -it --rm \
--workdir /app \
--volume ./:/app \
--env CI_COMMIT_TAG=$1 \
--uidmap 1000:0:1 --uidmap 0:1:1000 \
categulario/makepkg ./scripts/release-aur-git.sh

13
scripts/podman-build.sh Normal file
View File

@ -0,0 +1,13 @@
#!/bin/bash
if [[ -z $1 ]]; then
echo "please pass a tag as first argument. Something like v1.6.0"
exit 1
fi
podman run -it --rm \
--workdir /app \
--volume ./:/app \
--volume tiempo_cargo_index:/usr/local/cargo/registry \
--env CI_COMMIT_TAG=$1 \
tiempo-build-env ./scripts/build.sh

View File

@ -24,7 +24,7 @@ depends=()
optdepends=('sqlite: for manually editing the database')
provides=('$PROJECT_NAME')
conflicts=('$PROJECT_NAME')
source=(\"https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/packages/generic/$CI_COMMIT_TAG/$CI_COMMIT_TAG/$PROJECT_NAME-\${pkgver}-x86_64.tar.gz\")
source=(\"https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/packages/generic/$CI_COMMIT_TAG/$CI_COMMIT_TAG/$PROJECT_NAME-v\${pkgver}-x86_64.tar.gz\")
sha256sums=('$SUM')
package() {

12
scripts/uninstall.sh Normal file
View File

@ -0,0 +1,12 @@
#!/bin/bash
rm -f /usr/bin/t
prefix=${1:-/usr}
rm -f $prefix/bin/t
rm -rf $prefix/share/doc/tiempo/
rm -f $prefix/share/fish/vendor_completions.d/t.fish
rm -f $prefix/share/bash-completion/completions/t
rm -f $prefix/share/zsh/site-functions/_t
rm -f $prefix/share/man/man1/tiempo.1.gz

80
src/bin/t.rs Normal file
View File

@ -0,0 +1,80 @@
use std::convert::TryInto;
use std::process::exit;
use std::io;
use clap::ArgMatches;
use chrono::Utc;
use regex::Regex;
use lazy_static::lazy_static;
use tiempo::error;
use tiempo::database::SqliteDatabase;
use tiempo::env::Env;
use tiempo::config::Config;
use tiempo::commands::{
Command, Facts, r#in::InCommand, display::DisplayCommand,
sheet::SheetCommand, today::TodayCommand, yesterday::YesterdayCommand,
week::WeekCommand, month::MonthCommand, list::ListCommand, out::OutCommand,
resume::ResumeCommand, backend::BackendCommand, kill::KillCommand,
now::NowCommand, edit::EditCommand, archive::ArchiveCommand,
configure::ConfigureCommand,
};
use tiempo::io::Streams;
use tiempo::cli::make_cli;
lazy_static! {
// https://regex101.com/r/V9zYQu/1/
pub static ref NUMBER_RE: Regex = Regex::new(r"^\d+$").unwrap();
}
fn error_trap(matches: ArgMatches) -> error::Result<()> {
let env = Env::read();
let facts = Facts {
config: Config::read(env.timetrap_config_file.as_deref())?,
env,
now: Utc::now(),
};
if let Some(_matches) = matches.subcommand_matches("backend") {
return BackendCommand::handle(&facts.config);
}
let mut streams = Streams {
db: SqliteDatabase::from_path_or_create(&facts.config.database_file)?,
r#in: io::BufReader::new(io::stdin()),
out: io::stdout(),
err: io::stderr(),
};
match matches.subcommand() {
Some(("in", matches)) => InCommand::handle(matches.try_into()?, &mut streams, &facts),
Some(("out", matches)) => OutCommand::handle(matches.try_into()?, &mut streams, &facts),
Some(("resume", matches)) => ResumeCommand::handle(matches.try_into()?, &mut streams, &facts),
Some(("display", matches)) => DisplayCommand::handle(matches.try_into()?, &mut streams, &facts),
Some(("today", matches)) => TodayCommand::handle(matches.try_into()?, &mut streams, &facts),
Some(("yesterday", matches)) => YesterdayCommand::handle(matches.try_into()?, &mut streams, &facts),
Some(("week", matches)) => WeekCommand::handle(matches.try_into()?, &mut streams, &facts),
Some(("month", matches)) => MonthCommand::handle(matches.try_into()?, &mut streams, &facts),
Some(("sheet", matches)) => SheetCommand::handle(matches.try_into()?, &mut streams, &facts),
Some(("list", matches)) => ListCommand::handle(matches.try_into()?, &mut streams, &facts),
Some(("kill", matches)) => KillCommand::handle(matches.try_into()?, &mut streams, &facts),
Some(("now", matches)) => NowCommand::handle(matches.try_into()?, &mut streams, &facts),
Some(("edit", matches)) => EditCommand::handle(matches.try_into()?, &mut streams, &facts),
Some(("archive", matches)) => ArchiveCommand::handle(matches.try_into()?, &mut streams, &facts),
Some(("configure", matches)) => ConfigureCommand::handle(matches.try_into()?, &mut streams, &facts),
Some((cmd, _)) => Err(error::Error::UnimplementedCommand(cmd.into())),
None => Err(error::Error::MissingSubcommand),
}
}
fn main() {
let matches = make_cli().get_matches();
if let Err(e) = error_trap(matches) {
eprintln!("{}", e);
exit(1);
}
}

View File

@ -1,107 +1,30 @@
use std::convert::TryInto;
use std::process::exit;
use std::io;
use clap::{
App, Arg, SubCommand, AppSettings, ArgMatches, crate_version, crate_authors,
crate_description, crate_name,
Command, Arg, SubCommand, command, value_parser,
};
use chrono::Utc;
use regex::Regex;
use lazy_static::lazy_static;
use tiempo::error;
use tiempo::database::SqliteDatabase;
use tiempo::env::Env;
use tiempo::config::Config;
use tiempo::commands::{
Command, Facts, r#in::InCommand, display::DisplayCommand,
sheet::SheetCommand, today::TodayCommand, yesterday::YesterdayCommand,
week::WeekCommand, month::MonthCommand, list::ListCommand, out::OutCommand,
resume::ResumeCommand, backend::BackendCommand, kill::KillCommand,
now::NowCommand, edit::EditCommand, archive::ArchiveCommand,
configure::ConfigureCommand,
};
use tiempo::io::Streams;
lazy_static! {
// https://regex101.com/r/V9zYQu/1/
pub static ref NUMBER_RE: Regex = Regex::new(r"^\d+$").unwrap();
}
fn is_number(v: String) -> Result<(), String>{
if NUMBER_RE.is_match(&v) {
Ok(())
} else {
Err(format!("'{}' is not a valid number", v))
}
}
fn error_trap(matches: ArgMatches) -> error::Result<()> {
let env = Env::read();
let facts = Facts {
config: Config::read(env.timetrap_config_file.as_deref())?,
env,
now: Utc::now(),
};
if let Some(_matches) = matches.subcommand_matches("backend") {
return BackendCommand::handle(&facts.config);
}
let mut streams = Streams {
db: SqliteDatabase::from_path_or_create(&facts.config.database_file)?,
r#in: io::BufReader::new(io::stdin()),
out: io::stdout(),
err: io::stderr(),
};
match matches.subcommand() {
("in", Some(matches)) => InCommand::handle(matches.try_into()?, &mut streams, &facts),
("out", Some(matches)) => OutCommand::handle(matches.try_into()?, &mut streams, &facts),
("resume", Some(matches)) => ResumeCommand::handle(matches.try_into()?, &mut streams, &facts),
("display", Some(matches)) => DisplayCommand::handle(matches.try_into()?, &mut streams, &facts),
("today", Some(matches)) => TodayCommand::handle(matches.try_into()?, &mut streams, &facts),
("yesterday", Some(matches)) => YesterdayCommand::handle(matches.try_into()?, &mut streams, &facts),
("week", Some(matches)) => WeekCommand::handle(matches.try_into()?, &mut streams, &facts),
("month", Some(matches)) => MonthCommand::handle(matches.try_into()?, &mut streams, &facts),
("sheet", Some(matches)) => SheetCommand::handle(matches.try_into()?, &mut streams, &facts),
("list", Some(matches)) => ListCommand::handle(matches.try_into()?, &mut streams, &facts),
("kill", Some(matches)) => KillCommand::handle(matches.try_into()?, &mut streams, &facts),
("now", Some(matches)) => NowCommand::handle(matches.try_into()?, &mut streams, &facts),
("edit", Some(matches)) => EditCommand::handle(matches.try_into()?, &mut streams, &facts),
("archive", Some(matches)) => ArchiveCommand::handle(matches.try_into()?, &mut streams, &facts),
("configure", Some(matches)) => ConfigureCommand::handle(matches.try_into()?, &mut streams, &facts),
(cmd, _) => Err(error::Error::UnimplementedCommand(cmd.into())),
}
}
fn main() {
pub fn make_cli() -> Command<'static> {
// Let's first declare some args that repeat here and there
let start_arg = Arg::with_name("start")
.long("start").short("s")
.long("start").short('s')
.takes_value(true).value_name("TIME")
.help("Include entries that start on this date or later");
let end_arg = Arg::with_name("end")
.long("end").short("e")
.long("end").short('e')
.takes_value(true).value_name("TIME")
.help("Include entries that start on this date or earlier");
let ids_arg = Arg::with_name("ids")
.short("v").long("ids")
.short('v').long("ids")
.help("Print database ids (for use with edit)");
let grep_arg = Arg::with_name("grep")
.long("grep").short("g")
.long("grep").short('g')
.takes_value(true).value_name("REGEXP")
.help("Only include entries whose note matches this regular expression");
let format_arg = Arg::with_name("format")
.short("f").long("format")
.short('f').long("format")
.takes_value(true).value_name("FORMAT")
.help(
"The output format. Valid built-in formats are chart, text, ical, \
@ -125,22 +48,18 @@ fn main() {
let id_arg = Arg::with_name("id")
.long("id")
.takes_value(true).value_name("ID")
.validator(is_number);
.value_parser(value_parser!(u64));
let interactive_arg = Arg::with_name("interactive")
.short("i")
.short('i')
.long("interactive")
.takes_value(false)
.conflicts_with("id")
.help("Choose an entry of the (unique) last N interactively");
// Now declar this app's cli
let matches = App::new("Tiempo")
.name(crate_name!())
.setting(AppSettings::SubcommandRequired)
.version(crate_version!())
.author(crate_authors!())
.about(crate_description!())
let cli = command!()
.subcommand_required(true)
.subcommand(SubCommand::with_name("archive")
.visible_alias("a")
@ -150,11 +69,11 @@ fn main() {
.arg(grep_arg.clone())
.arg(sheet_arg.clone().help("Archive entries from this sheet instead of the current one"))
.arg(Arg::with_name("fake")
.short("f").long("fake")
.short('f').long("fake")
.help("Don't actually archive the entries, just display them")
)
.arg(Arg::with_name("time")
.short("t").long("time")
.short('t').long("time")
.takes_value(true).value_name("HOURS")
.help("Time in hours to archive. Archived time will be equal or less than this.")
)
@ -172,7 +91,7 @@ fn main() {
.long("round-in-seconds")
.takes_value(true)
.value_name("SECONDS")
.validator(is_number)
.value_parser(value_parser!(u64))
.help("The duration of time to use for rounding with the -r flag. Default: 900 (15 m)"))
.arg(Arg::with_name("database_file")
.long("database-file")
@ -216,13 +135,13 @@ fn main() {
.long("week-start")
.takes_value(true)
.value_name("DAY")
.possible_values(&["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"])
.possible_values(["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"])
.help("The day of the week to use as the start of the week for t week. Default: monday"))
.arg(Arg::with_name("interactive_entries")
.long("interactive-entries")
.takes_value(true)
.value_name("N")
.validator(is_number)
.value_parser(value_parser!(u64))
.help("How many unique previous notes to show when selecting interactively"))
)
@ -277,10 +196,10 @@ fn main() {
.arg(grep_arg.clone())
.arg(sheet_arg.clone())
.arg(Arg::with_name("month")
.long("month").short("m")
.long("month").short('m')
.takes_value(true).value_name("TIME")
.aliases(&["s", "start"])
.possible_values(&[
.possible_values([
"this", "current", "last", "jan", "january", "feb",
"february", "mar", "march", "apr", "april", "may", "jun",
"june", "jul", "july", "aug", "august", "sep", "september",
@ -328,10 +247,10 @@ fn main() {
.visible_alias("l")
.about("List existing sheets")
.arg(Arg::with_name("all")
.short("a").long("all")
.short('a').long("all")
.help("List archive sheets also"))
.arg(Arg::with_name("flat")
.short("f").long("flat")
.short('f').long("flat")
.help("show only the sheet names"))
)
@ -342,12 +261,12 @@ fn main() {
.arg(Arg::with_name("sheet")
.takes_value(true).value_name("SHEET")
.conflicts_with_all(&["id", "last"])
.required_unless_one(&["id", "last"])
.required_unless_one(["id", "last"])
.help(
"Delete an entire sheet by its name"
))
.arg(Arg::with_name("last")
.short("l").long("last")
.short('l').long("last")
.takes_value(false)
.help("Delete the last entry of the current sheet"))
)
@ -365,12 +284,12 @@ fn main() {
.arg(end_arg.clone().help("Set this as the end time"))
.arg(
Arg::with_name("append")
.long("append").short("z")
.long("append").short('z')
.help("Append to the current note instead of replacing it. The delimiter between appended notes is configurable (see configure)")
)
.arg(
Arg::with_name("move")
.short("m").long("move")
.short('m').long("move")
.takes_value(true)
.value_name("SHEET")
.help("Move entry to another sheet")
@ -381,12 +300,7 @@ fn main() {
.value_name("NOTE")
.help("The note text. It will replace the previous one unless --append is given")
)
)
);
.get_matches();
if let Err(e) = error_trap(matches) {
eprintln!("{}", e);
exit(1);
}
cli
}

View File

@ -64,7 +64,7 @@ impl Default for Facts {
}
pub trait Command<'a> {
type Args: TryFrom<&'a ArgMatches<'a>>;
type Args: TryFrom<&'a ArgMatches>;
fn handle<D: Database, I: BufRead, O: Write, E: Write>(args: Self::Args, streams: &mut Streams<D, I, O, E>, facts: &Facts) -> Result<()>;
}

View File

@ -26,7 +26,7 @@ pub struct Args {
sheet: Option<String>,
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(matches: &'a ArgMatches) -> Result<Self> {
@ -274,22 +274,22 @@ mod tests {
fn entries_are_split_properly() {
let mut old_entry = Entry {
id: 1,
start: Utc.ymd(2022, 7, 29).and_hms(10, 0, 0),
end: Some(Utc.ymd(2022, 7, 29).and_hms(11, 0, 0)),
start: Utc.with_ymd_and_hms(2022, 7, 29, 10, 0, 0).unwrap(),
end: Some(Utc.with_ymd_and_hms(2022, 7, 29, 11, 0, 0).unwrap()),
note: Some("an entry".to_string()),
sheet: "foo".to_string(),
};
assert_eq!(split_entry(&mut old_entry, Duration::minutes(25)), (
Utc.ymd(2022, 7, 29).and_hms(10, 25, 0),
Some(Utc.ymd(2022, 7, 29).and_hms(11, 0, 0)),
Utc.with_ymd_and_hms(2022, 7, 29, 10, 25, 0).unwrap(),
Some(Utc.with_ymd_and_hms(2022, 7, 29, 11, 0, 0).unwrap()),
Some("an entry".to_string()),
"foo".to_string(),
));
assert_eq!(old_entry, Entry {
id: 1,
start: Utc.ymd(2022, 7, 29).and_hms(10, 0, 0),
end: Some(Utc.ymd(2022, 7, 29).and_hms(10, 25, 0)),
start: Utc.with_ymd_and_hms(2022, 7, 29, 10, 0, 0).unwrap(),
end: Some(Utc.with_ymd_and_hms(2022, 7, 29, 10, 25, 0).unwrap()),
note: Some("an entry".to_string()),
sheet: "foo".to_string(),
});
@ -394,7 +394,7 @@ Proceed? [y/N] ");
};
let mut streams = Streams::fake(b"y\n");
let facts = Facts::new();
let time_a = Utc.ymd(2022, 8, 1).and_hms(10, 0, 0);
let time_a = Utc.with_ymd_and_hms(2022, 8, 1, 10, 0, 0).unwrap();
let time_b = time_a + Duration::minutes(90);
let time_d = time_a + Duration::hours(3);

View File

@ -53,14 +53,14 @@ impl Args {
fn yes_no_none(matches: &ArgMatches, opt: &str) -> Option<bool> {
if matches.is_present(opt) {
Some(true)
} else if matches.is_present(&format!("no_{}", opt)) {
} else if matches.is_present(format!("no_{}", opt)) {
Some(false)
} else {
None
}
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(matches: &'a ArgMatches) -> Result<Self> {

View File

@ -98,7 +98,7 @@ pub struct Args {
sheet: Option<Sheet>,
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(matches: &'a ArgMatches) -> Result<Args> {
@ -178,14 +178,14 @@ mod tests {
fn filter_by_start() {
let args = Args {
format: Some(Formatter::Csv),
start: Some(Utc.ymd(2021, 6, 30).and_hms(10, 5, 0)),
start: Some(Utc.with_ymd_and_hms(2021, 6, 30, 10, 5, 0).unwrap()),
..Default::default()
};
let mut streams = Streams::fake(b"");
let facts = Facts::new();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 0, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 10, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
DisplayCommand::handle(args, &mut streams, &facts).unwrap();
@ -204,8 +204,8 @@ mod tests {
let mut streams = Streams::fake(b"");
let facts = Facts::new();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("adios".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 0, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 10, 0).unwrap(), None, Some("adios".into()), "default").unwrap();
entries_for_display(None, None, None, &mut streams, Formatter::Csv, true, Some("io".parse().unwrap()), &facts).unwrap();
@ -229,9 +229,9 @@ mod tests {
let facts = Facts::new();
std::env::set_var("TZ", "CST+6");
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), Some(Utc.ymd(2021, 6, 30).and_hms(11, 0, 0)), None, "sheet1").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(11, 0, 0), Some(Utc.ymd(2021, 6, 30).and_hms(12, 0, 0)), None, "sheet2").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(12, 0, 0), Some(Utc.ymd(2021, 6, 30).and_hms(13, 0, 0)), None, "sheet1").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 6, 30, 11, 0, 0).unwrap()), None, "sheet1").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 11, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 6, 30, 12, 0, 0).unwrap()), None, "sheet2").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 12, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 6, 30, 13, 0, 0).unwrap()), None, "sheet1").unwrap();
DisplayCommand::handle(args, &mut streams, &facts).unwrap();
@ -264,9 +264,9 @@ Timesheet: sheet2
let facts = Facts::new();
std::env::set_var("TZ", "CST+6");
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), Some(Utc.ymd(2021, 6, 30).and_hms(11, 0, 0)), None, "sheet1").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(11, 0, 0), Some(Utc.ymd(2021, 6, 30).and_hms(12, 0, 0)), None, "_sheet2").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(12, 0, 0), Some(Utc.ymd(2021, 6, 30).and_hms(13, 0, 0)), None, "sheet1").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 6, 30, 11, 0, 0).unwrap()), None, "sheet1").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 11, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 6, 30, 12, 0, 0).unwrap()), None, "_sheet2").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 12, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 6, 30, 13, 0, 0).unwrap()), None, "sheet1").unwrap();
DisplayCommand::handle(args, &mut streams, &facts).unwrap();
@ -296,8 +296,8 @@ Timesheet: sheet1
let args = Args {
format: Some(Formatter::Csv),
start: Some(Utc.ymd(2021, 6, 29).and_hms(12, 0, 0)),
end: Some(Utc.ymd(2021, 6, 29).and_hms(13, 0, 0)),
start: Some(Utc.with_ymd_and_hms(2021, 6, 29, 12, 0, 0).unwrap()),
end: Some(Utc.with_ymd_and_hms(2021, 6, 29, 13, 0, 0).unwrap()),
..Default::default()
};
let mut streams = Streams::fake(b"").with_db(
@ -332,8 +332,8 @@ Timesheet: sheet1
..Default::default()
});
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 0, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 10, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
DisplayCommand::handle(args, &mut streams, &facts).unwrap();
@ -357,8 +357,8 @@ Timesheet: sheet1
..Default::default()
});
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 0, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 10, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
DisplayCommand::handle(args, &mut streams, &facts).unwrap();

View File

@ -32,7 +32,7 @@ impl Args {
}
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(matches: &'a ArgMatches) -> Result<Self> {
@ -142,7 +142,7 @@ mod tests {
note: Some("new note".into()),
..Default::default()
};
let now = Utc.ymd(2021, 8, 3).and_hms(20, 29, 0);
let now = Utc.with_ymd_and_hms(2021, 8, 3, 20, 29, 0).unwrap();
let an_hour_ago = now - Duration::hours(1);
let facts = Facts::new().with_now(now);
@ -175,7 +175,7 @@ mod tests {
note: Some("new note".into()),
..Default::default()
};
let now = Utc.ymd(2021, 8, 3).and_hms(20, 29, 0);
let now = Utc.with_ymd_and_hms(2021, 8, 3, 20, 29, 0).unwrap();
let an_hour_ago = now - Duration::hours(1);
let facts = Facts::new().with_now(now);
@ -198,7 +198,7 @@ mod tests {
fn edit_start() {
std::env::set_var("TZ", "CST+6");
let mut streams = Streams::fake(b"");
let now = Utc.ymd(2021, 8, 3).and_hms(20, 29, 0);
let now = Utc.with_ymd_and_hms(2021, 8, 3, 20, 29, 0).unwrap();
let args = Args {
start: Some(now - Duration::minutes(30)),
..Default::default()
@ -224,7 +224,7 @@ mod tests {
fn edit_end() {
std::env::set_var("TZ", "CST+6");
let mut streams = Streams::fake(b"");
let now = Utc.ymd(2021, 8, 3).and_hms(20, 29, 0);
let now = Utc.with_ymd_and_hms(2021, 8, 3, 20, 29, 0).unwrap();
let args = Args {
end: Some(now - Duration::minutes(30)),
..Default::default()
@ -255,7 +255,7 @@ mod tests {
append: true,
..Default::default()
};
let now = Utc.ymd(2021, 8, 3).and_hms(20, 29, 0);
let now = Utc.with_ymd_and_hms(2021, 8, 3, 20, 29, 0).unwrap();
let an_hour_ago = now - Duration::hours(1);
let facts = Facts::new().with_now(now);
@ -277,7 +277,7 @@ mod tests {
fn edit_move() {
std::env::set_var("TZ", "CST+6");
let mut streams = Streams::fake(b"");
let now = Utc.ymd(2021, 8, 3).and_hms(20, 29, 0);
let now = Utc.with_ymd_and_hms(2021, 8, 3, 20, 29, 0).unwrap();
let args = Args {
r#move: Some("new sheet".to_owned()),
..Default::default()
@ -309,7 +309,7 @@ mod tests {
append: true,
..Default::default()
};
let now = Utc.ymd(2021, 8, 3).and_hms(20, 29, 0);
let now = Utc.with_ymd_and_hms(2021, 8, 3, 20, 29, 0).unwrap();
let an_hour_ago = now - Duration::hours(1);
let facts = Facts::new().with_now(now).with_config(Config {
append_notes_delimiter: ";".to_owned(),
@ -346,8 +346,8 @@ mod tests {
let mut streams = Streams::fake(b"").with_db(
SqliteDatabase::from_path(&database_file).unwrap()
);
let now = Utc.ymd(2021, 8, 3).and_hms(20, 29, 0);
let new_end = Utc.ymd(2021, 6, 29).and_hms(14, 26, 52);
let now = Utc.with_ymd_and_hms(2021, 8, 3, 20, 29, 0).unwrap();
let new_end = Utc.with_ymd_and_hms(2021, 6, 29, 14, 26, 52).unwrap();
let args = Args {
end: Some(new_end),
..Default::default()

View File

@ -18,7 +18,7 @@ pub struct Args {
pub note: Option<String>,
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(matches: &'a ArgMatches) -> Result<Self> {

View File

@ -17,7 +17,7 @@ pub enum Args {
Last,
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(args: &'a ArgMatches) -> Result<Args> {

View File

@ -22,7 +22,7 @@ pub struct Args {
flat: bool,
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(matches: &ArgMatches) -> Result<Args> {
@ -45,7 +45,7 @@ impl<'a> Command<'a> for ListCommand {
O: Write,
E: Write,
{
let today = facts.now.with_timezone(&Local).date().and_hms(0, 0, 0).with_timezone(&Utc);
let today = facts.now.with_timezone(&Local).date_naive().and_hms_opt(0, 0, 0).unwrap().and_local_timezone(Utc).unwrap();
let entries = if args.all {
streams.db.entries_full(None, None)?
} else {
@ -180,13 +180,13 @@ mod tests {
streams.db.set_current_sheet("sheet2").unwrap();
streams.db.set_last_sheet("sheet4").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 1, 1).and_hms(0, 0, 0), Some(Utc.ymd(2021, 1, 1).and_hms(1, 0, 0)), None, "_archived").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 1, 1).and_hms(0, 0, 0), Some(Utc.ymd(2021, 1, 1).and_hms(10,13, 55)), None, "sheet1").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 1, 1).and_hms(0, 0, 0), Some(Utc.ymd(2021, 1, 1).and_hms(7, 39, 18)), None, "sheet3").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 1, 1).and_hms(12, 0, 0), Some(Utc.ymd(2021, 1, 1).and_hms(13, 52, 45)), None, "sheet3").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 1, 1).and_hms(12, 0, 0), None, None, "sheet4").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 0, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 1, 1, 1, 0, 0).unwrap()), None, "_archived").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 0, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 1, 1, 10,13, 55).unwrap()), None, "sheet1").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 0, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 1, 1, 7, 39, 18).unwrap()), None, "sheet3").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 12, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 1, 1, 13, 52, 45).unwrap()), None, "sheet3").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 12, 0, 0).unwrap(), None, None, "sheet4").unwrap();
let now = Utc.ymd(2021, 1, 1).and_hms(13, 52, 45);
let now = Utc.with_ymd_and_hms(2021, 1, 1, 13, 52, 45).unwrap();
let facts = Facts::new().with_now(now);
ListCommand::handle(args, &mut streams, &facts).unwrap();
@ -230,7 +230,7 @@ mod tests {
SqliteDatabase::from_path("assets/test_list_old_database.db").unwrap()
);
let now = Local.ymd(2021, 7, 16).and_hms(11, 30, 45);
let now = Local.with_ymd_and_hms(2021, 7, 16, 11, 30, 45).unwrap();
let facts = Facts::new().with_now(now.with_timezone(&Utc));
ListCommand::handle(args, &mut streams, &facts).unwrap();
@ -257,13 +257,13 @@ mod tests {
streams.db.set_current_sheet("sheet2").unwrap();
streams.db.set_last_sheet("sheet4").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 1, 1).and_hms(0, 0, 0), Some(Utc.ymd(2021, 1, 1).and_hms(1, 0, 0)), None, "_archived").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 1, 1).and_hms(0, 0, 0), Some(Utc.ymd(2021, 1, 1).and_hms(10,13, 55)), None, "sheet1").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 1, 1).and_hms(0, 0, 0), Some(Utc.ymd(2021, 1, 1).and_hms(7, 39, 18)), None, "sheet3").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 1, 1).and_hms(12, 0, 0), Some(Utc.ymd(2021, 1, 1).and_hms(13, 52, 45)), None, "sheet3").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 1, 1).and_hms(12, 0, 0), None, None, "sheet4").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 0, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 1, 1, 1, 0, 0).unwrap()), None, "_archived").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 0, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 1, 1, 10,13, 55).unwrap()), None, "sheet1").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 0, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 1, 1, 7, 39, 18).unwrap()), None, "sheet3").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 12, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 1, 1, 13, 52, 45).unwrap()), None, "sheet3").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 12, 0, 0).unwrap(), None, None, "sheet4").unwrap();
let now = Utc.ymd(2021, 1, 1).and_hms(13, 52, 45);
let now = Utc.with_ymd_and_hms(2021, 1, 1, 13, 52, 45).unwrap();
let facts = Facts::new().with_now(now);
let args = Args {
flat: true,

View File

@ -16,31 +16,27 @@ use super::{Command, Facts, display::{Sheet, entries_for_display}};
/// Given a local datetime, returns the time when the month it belongs started
fn beginning_of_month(time: DateTime<Local>) -> DateTime<Utc> {
time.date().with_day(1).unwrap().and_hms(0, 0, 0).with_timezone(&Utc)
time.date_naive().with_day(1).unwrap().and_hms_opt(0, 0, 0).unwrap().and_local_timezone(Utc).unwrap()
}
/// Given a datetime compute the time where the previous_month started in UTC
fn beginning_of_previous_month(time: DateTime<Local>) -> DateTime<Utc> {
match time.month() {
1 => {
Local.ymd(time.year()-1, 12, 1).and_hms(0, 0, 0).with_timezone(&Utc)
Local.with_ymd_and_hms(time.year()-1, 12, 1, 0, 0, 0).unwrap().with_timezone(&Utc)
}
n => Local.ymd(time.year(), n-1, 1).and_hms(0, 0, 0).with_timezone(&Utc)
n => Local.with_ymd_and_hms(time.year(), n-1, 1, 0, 0, 0).unwrap().with_timezone(&Utc)
}
}
#[derive(Default)]
enum MonthSpec {
Last,
#[default]
This,
Month(u32),
}
impl Default for MonthSpec {
fn default() -> MonthSpec {
MonthSpec::This
}
}
impl FromStr for MonthSpec {
type Err = Error;
@ -74,7 +70,7 @@ pub struct Args {
sheet: Option<Sheet>,
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(matches: &'a ArgMatches) -> Result<Args> {
@ -110,21 +106,21 @@ impl<'a> Command<'a> for MonthCommand {
if month < now.month() {
// the specified month is in the current year
(
Local.ymd(now.year(), month, 1).and_hms(0, 0, 0).with_timezone(&Utc),
Local.with_ymd_and_hms(now.year(), month, 1, 0, 0, 0).unwrap().with_timezone(&Utc),
if month < 12 {
Local.ymd(now.year(), month+1, 1).and_hms(0, 0, 0).with_timezone(&Utc)
Local.with_ymd_and_hms(now.year(), month+1, 1, 0, 0, 0).unwrap().with_timezone(&Utc)
} else {
Local.ymd(now.year()+1, 1, 1).and_hms(0, 0, 0).with_timezone(&Utc)
Local.with_ymd_and_hms(now.year()+1, 1, 1, 0, 0, 0).unwrap().with_timezone(&Utc)
}
)
} else {
// use previous year
(
Local.ymd(now.year() - 1, month, 1).and_hms(0, 0, 0).with_timezone(&Utc),
Local.with_ymd_and_hms(now.year() - 1, month, 1, 0, 0, 0).unwrap().with_timezone(&Utc),
if month < 12 {
Local.ymd(now.year() - 1, month + 1, 1).and_hms(0, 0, 0).with_timezone(&Utc)
Local.with_ymd_and_hms(now.year() - 1, month + 1, 1, 0, 0, 0).unwrap().with_timezone(&Utc)
} else {
Local.ymd(now.year(), 1, 1).and_hms(0, 0, 0).with_timezone(&Utc)
Local.with_ymd_and_hms(now.year(), 1, 1, 0, 0, 0).unwrap().with_timezone(&Utc)
}
)
}
@ -156,14 +152,14 @@ mod tests {
let args = Default::default();
let mut streams = Streams::fake(b"");
let now = Utc.ymd(2021, 6, 30).and_hms(11, 0, 0);
let now = Utc.with_ymd_and_hms(2021, 6, 30, 11, 0, 0).unwrap();
let facts = Facts::new().with_config(Config {
default_formatter: Formatter::Ids,
..Default::default()
}).with_now(now);
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 0, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 10, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
MonthCommand::handle(args, &mut streams, &facts).unwrap();
@ -177,7 +173,7 @@ mod tests {
let args = Default::default();
let mut streams = Streams::fake(b"");
let now = Utc.ymd(2021, 6, 30).and_hms(11, 0, 0);
let now = Utc.with_ymd_and_hms(2021, 6, 30, 11, 0, 0).unwrap();
let facts = Facts::new().with_config(Config {
commands: CommandsSettings {
month: BaseCommandSettings {
@ -188,8 +184,8 @@ mod tests {
..Default::default()
}).with_now(now);
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 0, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 10, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
MonthCommand::handle(args, &mut streams, &facts).unwrap();

View File

@ -16,7 +16,7 @@ use super::{Command, Facts};
pub struct Args {
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(_matches: &'a ArgMatches) -> Result<Args> {
@ -101,17 +101,17 @@ mod tests {
std::env::set_var("TZ", "CST+6");
let mut streams = Streams::fake(b"");
let now = Utc.ymd(2021, 1, 1).and_hms(13, 52, 45);
let now = Utc.with_ymd_and_hms(2021, 1, 1, 13, 52, 45).unwrap();
let facts = Facts::new().with_now(now);
streams.db.set_current_sheet("sheet2").unwrap();
streams.db.set_last_sheet("sheet4").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 1, 1).and_hms(0, 0, 0), Some(Utc.ymd(2021, 1, 1).and_hms(1, 0, 0)), None, "_archived").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 1, 1).and_hms(0, 0, 0), Some(Utc.ymd(2021, 1, 1).and_hms(10,13, 55)), None, "sheet1").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 1, 1).and_hms(0, 0, 0), Some(Utc.ymd(2021, 1, 1).and_hms(7, 39, 18)), None, "sheet3").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 1, 1).and_hms(12, 0, 0), Some(Utc.ymd(2021, 1, 1).and_hms(13, 52, 45)), None, "sheet3").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 1, 1).and_hms(12, 0, 0), None, Some("some".to_string()), "sheet4").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 0, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 1, 1, 1, 0, 0).unwrap()), None, "_archived").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 0, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 1, 1, 10,13, 55).unwrap()), None, "sheet1").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 0, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 1, 1, 7, 39, 18).unwrap()), None, "sheet3").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 12, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 1, 1, 13, 52, 45).unwrap()), None, "sheet3").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 12, 0, 0).unwrap(), None, Some("some".to_string()), "sheet4").unwrap();
NowCommand::handle(Default::default(), &mut streams, &facts).unwrap();
@ -127,7 +127,7 @@ mod tests {
SqliteDatabase::from_path("assets/test_list_old_database.db").unwrap()
);
let now = Local.ymd(2021, 7, 16).and_hms(11, 30, 45);
let now = Local.with_ymd_and_hms(2021, 7, 16, 11, 30, 45).unwrap();
let facts = Facts::new().with_now(now.with_timezone(&Utc));
NowCommand::handle(Default::default(), &mut streams, &facts).unwrap();
@ -148,7 +148,7 @@ mod tests {
std::env::set_var("TZ", "CST+6");
let mut streams = Streams::fake(b"");
let now = Utc.ymd(2021, 1, 1).and_hms(13, 52, 45);
let now = Utc.with_ymd_and_hms(2021, 1, 1, 13, 52, 45).unwrap();
let facts = Facts::new().with_now(now);
NowCommand::handle(Default::default(), &mut streams, &facts).unwrap();

View File

@ -17,7 +17,7 @@ pub struct Args {
at: Option<DateTime<Utc>>,
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(matches: &'a ArgMatches) -> Result<Args> {

View File

@ -12,25 +12,21 @@ use crate::io::Streams;
use crate::interactive::note_from_last_entries;
use super::{Command, Facts, r#in, sheet};
#[derive(Default)]
enum SelectedEntry {
Id(u64),
Interactive,
#[default]
NotSpecified,
}
impl Default for SelectedEntry {
fn default() -> Self {
SelectedEntry::NotSpecified
}
}
#[derive(Default)]
pub struct Args {
entry: SelectedEntry,
at: Option<DateTime<Utc>>,
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(matches: &'a ArgMatches) -> Result<Self> {

View File

@ -14,7 +14,7 @@ pub struct Args {
pub sheet: Option<String>,
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(matches: &'a ArgMatches) -> Result<Self> {

View File

@ -2,7 +2,7 @@ use std::convert::TryFrom;
use std::io::{BufRead, Write};
use clap::ArgMatches;
use chrono::{DateTime, Utc, Local};
use chrono::{DateTime, Utc, Local, Timelike};
use regex::Regex;
use crate::error::{Result, Error};
@ -23,7 +23,7 @@ pub struct Args {
sheet: Option<Sheet>,
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(matches: &'a ArgMatches) -> Result<Args> {
@ -49,7 +49,13 @@ impl<'a> Command<'a> for TodayCommand {
O: Write,
E: Write,
{
let start = Some(facts.now.with_timezone(&Local).date().and_hms(0, 0, 0).with_timezone(&Utc));
let start = Some(facts.now
.with_timezone(&Local)
.with_hour(0).unwrap()
.with_minute(0).unwrap()
.with_second(0).unwrap()
.with_nanosecond(0).unwrap()
.with_timezone(&Utc));
entries_for_display(
start,
@ -81,10 +87,10 @@ mod tests {
let facts = Facts::new().with_config(Config {
default_formatter: Formatter::Ids,
..Default::default()
}).with_now(Utc.ymd(2021, 6, 30).and_hms(11, 0, 0));
}).with_now(Utc.with_ymd_and_hms(2021, 6, 30, 11, 0, 0).unwrap());
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 0, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 10, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
TodayCommand::handle(args, &mut streams, &facts).unwrap();
@ -106,10 +112,10 @@ mod tests {
..Default::default()
},
..Default::default()
}).with_now(Utc.ymd(2021, 6, 30).and_hms(11, 0, 0));
}).with_now(Utc.with_ymd_and_hms(2021, 6, 30, 11, 0, 0).unwrap());
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 0, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 10, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
TodayCommand::handle(args, &mut streams, &facts).unwrap();

View File

@ -2,7 +2,7 @@ use std::convert::TryFrom;
use std::io::{BufRead, Write};
use clap::ArgMatches;
use chrono::{DateTime, Utc, Local, Duration, Weekday, Datelike};
use chrono::{DateTime, Utc, Local, Duration, Weekday, Datelike, Timelike};
use regex::Regex;
use crate::error::{Result, Error};
@ -56,7 +56,12 @@ fn prev_day(now: DateTime<Local>, week_start: WeekDay) -> DateTime<Utc> {
_ => unreachable!(),
};
begining.date().and_hms(0, 0, 0).with_timezone(&Utc)
begining
.with_hour(0).unwrap()
.with_minute(0).unwrap()
.with_second(0).unwrap()
.with_nanosecond(0).unwrap()
.with_timezone(&Utc)
}
#[derive(Default)]
@ -68,7 +73,7 @@ pub struct Args {
sheet: Option<Sheet>,
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(matches: &'a ArgMatches) -> Result<Args> {
@ -120,15 +125,15 @@ mod tests {
#[test]
fn test_prev_day() {
// starting a saturday
let now = Local.ymd(2021, 7, 10).and_hms(18, 31, 0);
let now = Local.with_ymd_and_hms(2021, 7, 10, 18, 31, 0).unwrap();
assert_eq!(prev_day(now, WeekDay::Monday), Local.ymd(2021, 7, 5).and_hms(0, 0, 0).with_timezone(&Utc));
assert_eq!(prev_day(now, WeekDay::Tuesday), Local.ymd(2021, 7, 6).and_hms(0, 0, 0).with_timezone(&Utc));
assert_eq!(prev_day(now, WeekDay::Wednesday), Local.ymd(2021, 7, 7).and_hms(0, 0, 0).with_timezone(&Utc));
assert_eq!(prev_day(now, WeekDay::Thursday), Local.ymd(2021, 7, 8).and_hms(0, 0, 0).with_timezone(&Utc));
assert_eq!(prev_day(now, WeekDay::Friday), Local.ymd(2021, 7, 9).and_hms(0, 0, 0).with_timezone(&Utc));
assert_eq!(prev_day(now, WeekDay::Saturday), Local.ymd(2021, 7, 10).and_hms(0, 0, 0).with_timezone(&Utc));
assert_eq!(prev_day(now, WeekDay::Sunday), Local.ymd(2021, 7, 4).and_hms(0, 0, 0).with_timezone(&Utc));
assert_eq!(prev_day(now, WeekDay::Monday), Local.with_ymd_and_hms(2021, 7, 5, 0, 0, 0).unwrap().with_timezone(&Utc));
assert_eq!(prev_day(now, WeekDay::Tuesday), Local.with_ymd_and_hms(2021, 7, 6, 0, 0, 0).unwrap().with_timezone(&Utc));
assert_eq!(prev_day(now, WeekDay::Wednesday), Local.with_ymd_and_hms(2021, 7, 7, 0, 0, 0).unwrap().with_timezone(&Utc));
assert_eq!(prev_day(now, WeekDay::Thursday), Local.with_ymd_and_hms(2021, 7, 8, 0, 0, 0).unwrap().with_timezone(&Utc));
assert_eq!(prev_day(now, WeekDay::Friday), Local.with_ymd_and_hms(2021, 7, 9, 0, 0, 0).unwrap().with_timezone(&Utc));
assert_eq!(prev_day(now, WeekDay::Saturday), Local.with_ymd_and_hms(2021, 7, 10, 0, 0, 0).unwrap().with_timezone(&Utc));
assert_eq!(prev_day(now, WeekDay::Sunday), Local.with_ymd_and_hms(2021, 7, 4, 0, 0, 0).unwrap().with_timezone(&Utc));
}
#[test]
@ -137,14 +142,14 @@ mod tests {
let args = Default::default();
let mut streams = Streams::fake(b"");
let now = Utc.ymd(2021, 7, 1).and_hms(10, 0, 0);
let now = Utc.with_ymd_and_hms(2021, 7, 1, 10, 0, 0).unwrap();
let facts = Facts::new().with_config(Config {
default_formatter: Formatter::Ids,
..Default::default()
}).with_now(now);
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 0, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 10, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
WeekCommand::handle(args, &mut streams, &facts).unwrap();
@ -158,7 +163,7 @@ mod tests {
let args = Default::default();
let mut streams = Streams::fake(b"");
let now = Utc.ymd(2021, 7, 1).and_hms(10, 0, 0);
let now = Utc.with_ymd_and_hms(2021, 7, 1, 10, 0, 0).unwrap();
let facts = Facts::new().with_config(Config {
commands: CommandsSettings {
week: BaseCommandSettings {
@ -169,8 +174,8 @@ mod tests {
..Default::default()
}).with_now(now);
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 0, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 10, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
WeekCommand::handle(args, &mut streams, &facts).unwrap();

View File

@ -21,7 +21,7 @@ pub struct Args {
sheet: Option<Sheet>,
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(matches: &'a ArgMatches) -> Result<Args> {
@ -46,9 +46,9 @@ impl<'a> Command<'a> for YesterdayCommand {
O: Write,
E: Write,
{
let today = facts.now.with_timezone(&Local).date();
let start = Some((today - Duration::days(1)).and_hms(0, 0, 0).with_timezone(&Utc));
let end = Some(today.and_hms(0, 0, 0).with_timezone(&Utc));
let today = facts.now.with_timezone(&Local).date_naive();
let start = Some((today - Duration::days(1)).and_hms_opt(0, 0, 0).unwrap().and_local_timezone(Utc).unwrap());
let end = Some(today.and_hms_opt(0, 0, 0).unwrap().and_local_timezone(Utc).unwrap());
entries_for_display(
start,
@ -79,20 +79,20 @@ mod tests {
..Default::default()
};
let mut streams = Streams::fake(b"");
let two_days_ago = Local::now().date() - Duration::days(2);
let yesterday = Local::now().date() - Duration::days(1);
let today = Local::now().date();
let two_days_ago = Local::now().date_naive() - Duration::days(2);
let yesterday = Local::now().date_naive() - Duration::days(1);
let today = Local::now().date_naive();
let facts = Facts::new();
streams.db.entry_insert(two_days_ago.and_hms(1, 2, 3).with_timezone(&Utc), None, None, "default").unwrap();
streams.db.entry_insert(yesterday.and_hms(1, 2, 3).with_timezone(&Utc), None, Some("This!".into()), "default").unwrap();
streams.db.entry_insert(today.and_hms(1, 2, 3).with_timezone(&Utc), None, None, "default").unwrap();
streams.db.entry_insert(two_days_ago.and_hms_opt(1, 2, 3).unwrap().and_local_timezone(Utc).unwrap(), None, None, "default").unwrap();
streams.db.entry_insert(yesterday.and_hms_opt(1, 2, 3).unwrap().and_local_timezone(Utc).unwrap(), None, Some("This!".into()), "default").unwrap();
streams.db.entry_insert(today.and_hms_opt(1, 2, 3).unwrap().and_local_timezone(Utc).unwrap(), None, None, "default").unwrap();
YesterdayCommand::handle(args, &mut streams, &facts).unwrap();
assert_eq!(&String::from_utf8_lossy(&streams.out), &format!("start,end,note,sheet
{},,This!,default
", yesterday.and_hms(1, 2, 3).with_timezone(&Utc).to_rfc3339_opts(chrono::SecondsFormat::Micros, true)));
", yesterday.and_hms_opt(1, 2, 3).unwrap().and_local_timezone(Utc).unwrap().to_rfc3339_opts(chrono::SecondsFormat::Micros, true)));
assert_eq!(
String::from_utf8_lossy(&streams.err),
@ -106,14 +106,14 @@ mod tests {
let args = Default::default();
let mut streams = Streams::fake(b"");
let now = Utc.ymd(2021, 7, 1).and_hms(10, 0, 0);
let now = Utc.with_ymd_and_hms(2021, 7, 1, 10, 0, 0).unwrap();
let facts = Facts::new().with_config(Config {
default_formatter: Formatter::Ids,
..Default::default()
}).with_now(now);
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 0, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 10, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
YesterdayCommand::handle(args, &mut streams, &facts).unwrap();
@ -127,7 +127,7 @@ mod tests {
let args = Default::default();
let mut streams = Streams::fake(b"");
let now = Utc.ymd(2021, 7, 1).and_hms(10, 0, 0);
let now = Utc.with_ymd_and_hms(2021, 7, 1, 10, 0, 0).unwrap();
let facts = Facts::new().with_config(Config {
commands: CommandsSettings {
yesterday: BaseCommandSettings {
@ -138,8 +138,8 @@ mod tests {
..Default::default()
}).with_now(now);
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 0, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 6, 30, 10, 10, 0).unwrap(), None, Some("hola".into()), "default").unwrap();
YesterdayCommand::handle(args, &mut streams, &facts).unwrap();

View File

@ -324,7 +324,7 @@ impl Database for SqliteDatabase {
#[cfg(test)]
mod tests {
use chrono::TimeZone;
use chrono::{TimeZone, NaiveDate};
use pretty_assertions::assert_eq;
use super::*;
@ -334,21 +334,21 @@ mod tests {
let mut db = SqliteDatabase::from_memory().unwrap();
db.init().unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(1, 0, 0), None, None, "XXX").unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(1, 0, 0), None, None, "OOO").unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(2, 0, 0), None, None, "XXX").unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(2, 0, 0), None, None, "OOO").unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(3, 0, 0), None, None, "XXX").unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(3, 0, 0), None, None, "OOO").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 1, 0, 0).unwrap(), None, None, "XXX").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 1, 0, 0).unwrap(), None, None, "OOO").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(), None, None, "XXX").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(), None, None, "OOO").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 3, 0, 0).unwrap(), None, None, "XXX").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 3, 0, 0).unwrap(), None, None, "OOO").unwrap();
let start = Utc.ymd(2021, 7, 7).and_hms(1, 30, 0);
let end = Utc.ymd(2021, 7, 7).and_hms(2, 30, 0);
let start = Utc.with_ymd_and_hms(2021, 7, 7, 1, 30, 0).unwrap();
let end = Utc.with_ymd_and_hms(2021, 7, 7, 2, 30, 0).unwrap();
// filter by start and end
assert_eq!(
db.entries_by_sheet("XXX", Some(start), Some(end)).unwrap().into_iter().map(|e| e.start).collect::<Vec<_>>(),
vec![
Utc.ymd(2021, 7, 7).and_hms(2, 0, 0),
Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(),
]
);
@ -356,8 +356,8 @@ mod tests {
assert_eq!(
db.entries_by_sheet("XXX", Some(start), None).unwrap().into_iter().map(|e| e.start).collect::<Vec<_>>(),
vec![
Utc.ymd(2021, 7, 7).and_hms(2, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(3, 0, 0),
Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 3, 0, 0).unwrap(),
]
);
@ -365,8 +365,8 @@ mod tests {
assert_eq!(
db.entries_by_sheet("XXX", None, Some(end)).unwrap().into_iter().map(|e| e.start).collect::<Vec<_>>(),
vec![
Utc.ymd(2021, 7, 7).and_hms(1, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(2, 0, 0),
Utc.with_ymd_and_hms(2021, 7, 7, 1, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(),
]
);
@ -374,9 +374,9 @@ mod tests {
assert_eq!(
db.entries_by_sheet("XXX", None, None).unwrap().into_iter().map(|e| e.start).collect::<Vec<_>>(),
vec![
Utc.ymd(2021, 7, 7).and_hms(1, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(2, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(3, 0, 0),
Utc.with_ymd_and_hms(2021, 7, 7, 1, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 3, 0, 0).unwrap(),
]
);
}
@ -386,21 +386,21 @@ mod tests {
let mut db = SqliteDatabase::from_memory().unwrap();
db.init().unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(1, 0, 0), None, None, "XXX").unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(1, 0, 0), None, None, "_OO").unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(2, 0, 0), None, None, "XXX").unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(2, 0, 0), None, None, "_OO").unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(3, 0, 0), None, None, "XXX").unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(3, 0, 0), None, None, "_OO").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 1, 0, 0).unwrap(), None, None, "XXX").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 1, 0, 0).unwrap(), None, None, "_OO").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(), None, None, "XXX").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(), None, None, "_OO").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 3, 0, 0).unwrap(), None, None, "XXX").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 3, 0, 0).unwrap(), None, None, "_OO").unwrap();
let start = Utc.ymd(2021, 7, 7).and_hms(1, 30, 0);
let end = Utc.ymd(2021, 7, 7).and_hms(2, 30, 0);
let start = Utc.with_ymd_and_hms(2021, 7, 7, 1, 30, 0).unwrap();
let end = Utc.with_ymd_and_hms(2021, 7, 7, 2, 30, 0).unwrap();
// filter by start and end
assert_eq!(
db.entries_all_visible(Some(start), Some(end)).unwrap().into_iter().map(|e| e.start).collect::<Vec<_>>(),
vec![
Utc.ymd(2021, 7, 7).and_hms(2, 0, 0),
Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(),
]
);
@ -408,8 +408,8 @@ mod tests {
assert_eq!(
db.entries_all_visible(Some(start), None).unwrap().into_iter().map(|e| e.start).collect::<Vec<_>>(),
vec![
Utc.ymd(2021, 7, 7).and_hms(2, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(3, 0, 0),
Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 3, 0, 0).unwrap(),
]
);
@ -417,8 +417,8 @@ mod tests {
assert_eq!(
db.entries_all_visible(None, Some(end)).unwrap().into_iter().map(|e| e.start).collect::<Vec<_>>(),
vec![
Utc.ymd(2021, 7, 7).and_hms(1, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(2, 0, 0),
Utc.with_ymd_and_hms(2021, 7, 7, 1, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(),
]
);
@ -426,9 +426,9 @@ mod tests {
assert_eq!(
db.entries_all_visible(None, None).unwrap().into_iter().map(|e| e.start).collect::<Vec<_>>(),
vec![
Utc.ymd(2021, 7, 7).and_hms(1, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(2, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(3, 0, 0),
Utc.with_ymd_and_hms(2021, 7, 7, 1, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 3, 0, 0).unwrap(),
]
);
}
@ -438,22 +438,22 @@ mod tests {
let mut db = SqliteDatabase::from_memory().unwrap();
db.init().unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(1, 0, 0), None, None, "XXX").unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(1, 0, 0), None, None, "_OO").unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(2, 0, 0), None, None, "XXX").unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(2, 0, 0), None, None, "_OO").unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(3, 0, 0), None, None, "XXX").unwrap();
db.entry_insert(Utc.ymd(2021, 7, 7).and_hms(3, 0, 0), None, None, "_OO").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 1, 0, 0).unwrap(), None, None, "XXX").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 1, 0, 0).unwrap(), None, None, "_OO").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(), None, None, "XXX").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(), None, None, "_OO").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 3, 0, 0).unwrap(), None, None, "XXX").unwrap();
db.entry_insert(Utc.with_ymd_and_hms(2021, 7, 7, 3, 0, 0).unwrap(), None, None, "_OO").unwrap();
let start = Utc.ymd(2021, 7, 7).and_hms(1, 30, 0);
let end = Utc.ymd(2021, 7, 7).and_hms(2, 30, 0);
let start = Utc.with_ymd_and_hms(2021, 7, 7, 1, 30, 0).unwrap();
let end = Utc.with_ymd_and_hms(2021, 7, 7, 2, 30, 0).unwrap();
// filter by start and end
assert_eq!(
db.entries_full(Some(start), Some(end)).unwrap().into_iter().map(|e| e.start).collect::<Vec<_>>(),
vec![
Utc.ymd(2021, 7, 7).and_hms(2, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(2, 0, 0),
Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(),
]
);
@ -461,10 +461,10 @@ mod tests {
assert_eq!(
db.entries_full(Some(start), None).unwrap().into_iter().map(|e| e.start).collect::<Vec<_>>(),
vec![
Utc.ymd(2021, 7, 7).and_hms(2, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(3, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(2, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(3, 0, 0),
Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 3, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 3, 0, 0).unwrap(),
]
);
@ -472,10 +472,10 @@ mod tests {
assert_eq!(
db.entries_full(None, Some(end)).unwrap().into_iter().map(|e| e.start).collect::<Vec<_>>(),
vec![
Utc.ymd(2021, 7, 7).and_hms(1, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(2, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(1, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(2, 0, 0),
Utc.with_ymd_and_hms(2021, 7, 7, 1, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 1, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(),
]
);
@ -483,12 +483,12 @@ mod tests {
assert_eq!(
db.entries_full(None, None).unwrap().into_iter().map(|e| e.start).collect::<Vec<_>>(),
vec![
Utc.ymd(2021, 7, 7).and_hms(1, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(2, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(3, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(1, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(2, 0, 0),
Utc.ymd(2021, 7, 7).and_hms(3, 0, 0),
Utc.with_ymd_and_hms(2021, 7, 7, 1, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 3, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 1, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 2, 0, 0).unwrap(),
Utc.with_ymd_and_hms(2021, 7, 7, 3, 0, 0).unwrap(),
]
);
}
@ -503,10 +503,10 @@ mod tests {
let mut db = SqliteDatabase::from_memory().unwrap();
db.init().unwrap();
let sometime = Utc.ymd(2022, 7, 27);
let sometime = NaiveDate::from_ymd_opt(2022, 7, 27).unwrap();
db.entry_insert(sometime.and_hms(11, 0, 0), Some(sometime.and_hms(12, 0, 0)), Some("latest".into()), "foo").unwrap();
db.entry_insert(sometime.and_hms(10, 0, 0), Some(sometime.and_hms(11, 0, 0)), Some("oldest".into()), "foo").unwrap();
db.entry_insert(sometime.and_hms_opt(11, 0, 0).unwrap().and_local_timezone(Utc).unwrap(), Some(sometime.and_hms_opt(12, 0, 0).unwrap().and_local_timezone(Utc).unwrap()), Some("latest".into()), "foo").unwrap();
db.entry_insert(sometime.and_hms_opt(10, 0, 0).unwrap().and_local_timezone(Utc).unwrap(), Some(sometime.and_hms_opt(11, 0, 0).unwrap().and_local_timezone(Utc).unwrap()), Some("oldest".into()), "foo").unwrap();
// filter by start and end
assert_eq!(
@ -514,8 +514,8 @@ mod tests {
Entry {
id: 1,
note: Some("latest".into()),
start: sometime.and_hms(11, 0, 0),
end: Some(sometime.and_hms(12, 0, 0)),
start: sometime.and_hms_opt(11, 0, 0).unwrap().and_local_timezone(Utc).unwrap(),
end: Some(sometime.and_hms_opt(12, 0, 0).unwrap().and_local_timezone(Utc).unwrap()),
sheet: "foo".into(),
}
);

View File

@ -1,5 +1,5 @@
use std::process::{Command, Stdio};
use std::io::{Read, Write, Seek, SeekFrom};
use std::io::{Read, Write, Seek};
use tempfile::NamedTempFile;
@ -38,7 +38,7 @@ pub fn get_string(note_editor: Option<&str>, prev_contents: Option<String>) -> R
if let Some(contents) = prev_contents {
tmpfile.write_all(contents.as_bytes())?;
tmpfile.seek(SeekFrom::Start(0))?;
tmpfile.rewind()?;
}
c.arg(tmpfile.as_ref());

View File

@ -19,6 +19,9 @@ pub enum Error {
#[error("The subcommand '{0}' is not implemented")]
UnimplementedCommand(String),
#[error("A subcommand was not specified and no default command is set")]
MissingSubcommand,
/// Sometimes a specific variant for an error is not necessary if the error
/// can only happen in one place in the code. This is what the generic error
/// is for and nothing else.

View File

@ -15,9 +15,10 @@ pub mod ical;
pub mod custom;
pub mod chart;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Formatter {
#[default]
Text,
Csv,
Json,
@ -27,12 +28,6 @@ pub enum Formatter {
Custom(String),
}
impl Default for Formatter {
fn default() -> Formatter {
Formatter::Text
}
}
impl Formatter {
/// Prints the given entries to the specified output device.
///

View File

@ -3,7 +3,7 @@ use std::fmt::Write as _;
use std::collections::{HashMap, HashSet};
use crate::tabulate::{Tabulate, Col, Align::*};
use chrono::{Local, Datelike, Date, Duration};
use chrono::{Local, Datelike, NaiveDate, Duration};
use ansi_term::{Style, Color::{Green, Red, White, Fixed}};
use crate::commands::Facts;
@ -12,12 +12,12 @@ use crate::error::Result;
use crate::config::WeekDay;
struct Dates {
current: Date<Local>,
end: Date<Local>,
current: NaiveDate,
end: NaiveDate,
}
impl Dates {
fn range(from: Date<Local>, to: Date<Local>) -> Dates {
fn range(from: NaiveDate, to: NaiveDate) -> Dates {
Dates {
current: from,
end: to,
@ -26,7 +26,7 @@ impl Dates {
}
impl Iterator for Dates {
type Item = Date<Local>;
type Item = NaiveDate;
fn next(&mut self) -> Option<Self::Item> {
if self.current > self.end {
@ -34,7 +34,7 @@ impl Iterator for Dates {
} else {
let val = self.current;
self.current = self.current + Duration::days(1);
self.current += Duration::days(1);
Some(val)
}
@ -84,7 +84,7 @@ pub fn print_formatted<W: Write>(entries: Vec<Entry>, out: &mut W, facts: &Facts
let mut timesheets = HashSet::new();
for entry in entries.into_iter() {
let entrys_date = entry.start.with_timezone(&Local).date();
let entrys_date = entry.start.with_timezone(&Local).date_naive();
let hours = entry.hours(facts.now);
if first_date.is_none() {
@ -204,10 +204,10 @@ mod tests {
fn sample_printing() {
std::env::set_var("TZ", "CST+6");
let day1 = Utc.ymd(2022, 8, 15).and_hms(12, 0, 0);
let day2 = Utc.ymd(2022, 8, 16).and_hms(12, 0, 0);
let day3 = Utc.ymd(2022, 8, 17).and_hms(12, 0, 0);
let day4 = Utc.ymd(2022, 8, 18).and_hms(12, 0, 0);
let day1 = Utc.with_ymd_and_hms(2022, 8, 15, 12, 0, 0).unwrap();
let day2 = Utc.with_ymd_and_hms(2022, 8, 16, 12, 0, 0).unwrap();
let day3 = Utc.with_ymd_and_hms(2022, 8, 17, 12, 0, 0).unwrap();
let day4 = Utc.with_ymd_and_hms(2022, 8, 18, 12, 0, 0).unwrap();
let entries = vec![
Entry::new_sample(1, day1, Some(day1 + Duration::hours(5))),
@ -249,8 +249,8 @@ Timesheet: default
fn partitioned_week() {
std::env::set_var("TZ", "CST+6");
let day1 = Utc.ymd(2022, 8, 28).and_hms(12, 0, 0);
let day2 = Utc.ymd(2022, 8, 29).and_hms(12, 0, 0);
let day1 = Utc.with_ymd_and_hms(2022, 8, 28, 12, 0, 0).unwrap();
let day2 = Utc.with_ymd_and_hms(2022, 8, 29, 12, 0, 0).unwrap();
let entries = vec![
Entry::new_sample(1, day1, Some(day1 + Duration::hours(5))),
@ -290,8 +290,8 @@ Timesheet: default
fn days_without_hours_appear() {
std::env::set_var("TZ", "CST+6");
let day1 = Utc.ymd(2022, 8, 15).and_hms(12, 0, 0);
let day3 = Utc.ymd(2022, 8, 17).and_hms(12, 0, 0);
let day1 = Utc.with_ymd_and_hms(2022, 8, 15, 12, 0, 0).unwrap();
let day3 = Utc.with_ymd_and_hms(2022, 8, 17, 12, 0, 0).unwrap();
let entries = vec![
Entry::new_sample(1, day1, Some(day1 + Duration::hours(5))),
@ -318,10 +318,10 @@ Timesheet: default
fn display_without_goals_set() {
std::env::set_var("TZ", "CST+6");
let day1 = Utc.ymd(2022, 8, 15).and_hms(12, 0, 0);
let day2 = Utc.ymd(2022, 8, 16).and_hms(12, 0, 0);
let day3 = Utc.ymd(2022, 8, 17).and_hms(12, 0, 0);
let day4 = Utc.ymd(2022, 8, 18).and_hms(12, 0, 0);
let day1 = Utc.with_ymd_and_hms(2022, 8, 15, 12, 0, 0).unwrap();
let day2 = Utc.with_ymd_and_hms(2022, 8, 16, 12, 0, 0).unwrap();
let day3 = Utc.with_ymd_and_hms(2022, 8, 17, 12, 0, 0).unwrap();
let day4 = Utc.with_ymd_and_hms(2022, 8, 18, 12, 0, 0).unwrap();
let entries = vec![
Entry::new_sample(1, day1, Some(day1 + Duration::hours(5))),
@ -351,10 +351,10 @@ Timesheet: default
fn multiple_timesheets_to_display() {
std::env::set_var("TZ", "CST+6");
let day1 = Utc.ymd(2022, 8, 15).and_hms(12, 0, 0);
let day2 = Utc.ymd(2022, 8, 16).and_hms(12, 0, 0);
let day3 = Utc.ymd(2022, 8, 17).and_hms(12, 0, 0);
let day4 = Utc.ymd(2022, 8, 18).and_hms(12, 0, 0);
let day1 = Utc.with_ymd_and_hms(2022, 8, 15, 12, 0, 0).unwrap();
let day2 = Utc.with_ymd_and_hms(2022, 8, 16, 12, 0, 0).unwrap();
let day3 = Utc.with_ymd_and_hms(2022, 8, 17, 12, 0, 0).unwrap();
let day4 = Utc.with_ymd_and_hms(2022, 8, 18, 12, 0, 0).unwrap();
let entries = vec![
Entry::new_sample(1, day1, Some(day1 + Duration::hours(5))).with_sheet("var"),

View File

@ -46,8 +46,8 @@ mod tests {
#[test]
fn test_print_formatted() {
let entries = vec![
Entry::new_sample(1, Utc.ymd(2021, 6, 30).and_hms(18, 12, 34), Some(Utc.ymd(2021, 6, 30).and_hms(19, 0, 0))),
Entry::new_sample(2, Utc.ymd(2021, 6, 30).and_hms(18, 12, 34), None),
Entry::new_sample(1, Utc.with_ymd_and_hms(2021, 6, 30, 18, 12, 34).unwrap(), Some(Utc.with_ymd_and_hms(2021, 6, 30, 19, 0, 0).unwrap())),
Entry::new_sample(2, Utc.with_ymd_and_hms(2021, 6, 30, 18, 12, 34).unwrap(), None),
];
let mut out = Vec::new();
@ -62,8 +62,8 @@ mod tests {
#[test]
fn test_print_formatted_ids() {
let entries = vec![
Entry::new_sample(1, Utc.ymd(2021, 6, 30).and_hms(18, 12, 34), Some(Utc.ymd(2021, 6, 30).and_hms(19, 0, 0))),
Entry::new_sample(2, Utc.ymd(2021, 6, 30).and_hms(18, 12, 34), None),
Entry::new_sample(1, Utc.with_ymd_and_hms(2021, 6, 30, 18, 12, 34).unwrap(), Some(Utc.with_ymd_and_hms(2021, 6, 30, 19, 0, 0).unwrap())),
Entry::new_sample(2, Utc.with_ymd_and_hms(2021, 6, 30, 18, 12, 34).unwrap(), None),
];
let mut out = Vec::new();

View File

@ -81,7 +81,7 @@ pub fn print_formatted<W: Write>(entries: Vec<Entry>, out: &mut W, facts: &Facts
]);
}
let entries_by_date = group.group_by(|e| e.start.with_timezone(&Local).date());
let entries_by_date = group.group_by(|e| e.start.with_timezone(&Local).date_naive());
let mut total = Duration::seconds(0);
for (date, entries) in entries_by_date.into_iter() {
@ -158,13 +158,13 @@ mod tests {
std::env::set_var("TZ", "CST+6");
let mut output = Vec::new();
let entries = vec![
Entry::new_sample(1, Utc.ymd(2008, 10, 3).and_hms(12, 0, 0), Some(Utc.ymd(2008, 10, 3).and_hms(14, 0, 0))),
Entry::new_sample(2, Utc.ymd(2008, 10, 3).and_hms(16, 0, 0), Some(Utc.ymd(2008, 10, 3).and_hms(18, 0, 0))),
Entry::new_sample(3, Utc.ymd(2008, 10, 5).and_hms(16, 0, 0), Some(Utc.ymd(2008, 10, 5).and_hms(18, 0, 0))),
Entry::new_sample(4, Utc.ymd(2008, 10, 5).and_hms(18, 0, 0), None),
Entry::new_sample(1, Utc.with_ymd_and_hms(2008, 10, 3, 12, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2008, 10, 3, 14, 0, 0).unwrap())),
Entry::new_sample(2, Utc.with_ymd_and_hms(2008, 10, 3, 16, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2008, 10, 3, 18, 0, 0).unwrap())),
Entry::new_sample(3, Utc.with_ymd_and_hms(2008, 10, 5, 16, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2008, 10, 5, 18, 0, 0).unwrap())),
Entry::new_sample(4, Utc.with_ymd_and_hms(2008, 10, 5, 18, 0, 0).unwrap(), None),
];
let now = Utc.ymd(2008, 10, 5).and_hms(20, 0, 0);
let now = Utc.with_ymd_and_hms(2008, 10, 5, 20, 0, 0).unwrap();
let facts = Facts::new().with_now(now);
print_formatted(entries, &mut output, &facts, false).unwrap();
@ -187,10 +187,13 @@ mod tests {
std::env::set_var("TZ", "CST+6");
let mut output = Vec::new();
let entries = vec![
Entry::new_sample(1, Utc.ymd(2008, 10, 3).and_hms_milli(12, 0, 0, 432), Some(Utc.ymd(2008, 10, 3).and_hms_milli(14, 0, 0, 312))),
Entry::new_sample(
1,
Utc.with_ymd_and_hms(2008, 10, 3, 12, 0, 0).unwrap().with_nanosecond(432_000_000).unwrap(),
Some(Utc.with_ymd_and_hms(2008, 10, 3, 14, 0, 0).unwrap().with_nanosecond(312_000_000).unwrap())),
];
let now = Utc.ymd(2008, 10, 5).and_hms(20, 0, 0);
let now = Utc.with_ymd_and_hms(2008, 10, 5, 20, 0, 0).unwrap();
let facts = Facts::new().with_now(now);
print_formatted(entries, &mut output, &facts, false).unwrap();
@ -209,11 +212,11 @@ mod tests {
std::env::set_var("TZ", "CST+6");
let mut output = Vec::new();
let entries = vec![
Entry::new_sample(1, Utc.ymd(2008, 10, 1).and_hms(12, 0, 0), Some(Utc.ymd(2008, 10, 3).and_hms(14, 0, 0))),
Entry::new_sample(2, Utc.ymd(2008, 10, 3).and_hms(12, 0, 0), Some(Utc.ymd(2008, 10, 3).and_hms(14, 0, 0))),
Entry::new_sample(1, Utc.with_ymd_and_hms(2008, 10, 1, 12, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2008, 10, 3, 14, 0, 0).unwrap())),
Entry::new_sample(2, Utc.with_ymd_and_hms(2008, 10, 3, 12, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2008, 10, 3, 14, 0, 0).unwrap())),
];
let now = Utc.ymd(2008, 10, 5).and_hms(20, 0, 0);
let now = Utc.with_ymd_and_hms(2008, 10, 5, 20, 0, 0).unwrap();
let facts = Facts::new().with_now(now);
print_formatted(entries, &mut output, &facts, false).unwrap();
@ -234,13 +237,13 @@ mod tests {
std::env::set_var("TZ", "CST+6");
let mut output = Vec::new();
let entries = vec![
Entry::new_sample(1, Utc.ymd(2008, 10, 3).and_hms(12, 0, 0), Some(Utc.ymd(2008, 10, 3).and_hms(14, 0, 0))),
Entry::new_sample(2, Utc.ymd(2008, 10, 3).and_hms(16, 0, 0), Some(Utc.ymd(2008, 10, 3).and_hms(18, 0, 0))),
Entry::new_sample(3, Utc.ymd(2008, 10, 5).and_hms(16, 0, 0), Some(Utc.ymd(2008, 10, 5).and_hms(18, 0, 0))),
Entry::new_sample(4, Utc.ymd(2008, 10, 5).and_hms(18, 0, 0), None),
Entry::new_sample(1, Utc.with_ymd_and_hms(2008, 10, 3, 12, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2008, 10, 3, 14, 0, 0).unwrap())),
Entry::new_sample(2, Utc.with_ymd_and_hms(2008, 10, 3, 16, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2008, 10, 3, 18, 0, 0).unwrap())),
Entry::new_sample(3, Utc.with_ymd_and_hms(2008, 10, 5, 16, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2008, 10, 5, 18, 0, 0).unwrap())),
Entry::new_sample(4, Utc.with_ymd_and_hms(2008, 10, 5, 18, 0, 0).unwrap(), None),
];
let now = Utc.ymd(2008, 10, 5).and_hms(20, 0, 0);
let now = Utc.with_ymd_and_hms(2008, 10, 5, 20, 0, 0).unwrap();
let facts = Facts::new().with_now(now);
print_formatted(entries, &mut output, &facts, true).unwrap();
@ -266,13 +269,13 @@ mod tests {
Entry {
id: 60000,
sheet: "default".into(),
start: Utc.ymd(2008, 10, 5).and_hms(16, 0, 0),
end: Some(Utc.ymd(2008, 10, 5).and_hms(18, 0, 0)),
start: Utc.with_ymd_and_hms(2008, 10, 5, 16, 0, 0).unwrap(),
end: Some(Utc.with_ymd_and_hms(2008, 10, 5, 18, 0, 0).unwrap()),
note: Some(LONG_NOTE.into()),
},
];
let now = Utc.ymd(2008, 10, 5).and_hms(20, 0, 0);
let now = Utc.with_ymd_and_hms(2008, 10, 5, 20, 0, 0).unwrap();
let facts = Facts::new().with_now(now);
print_formatted(entries, &mut output, &facts, true).unwrap();
@ -301,13 +304,13 @@ mod tests {
Entry {
id: 1,
sheet: "default".into(),
start: Utc.ymd(2008, 10, 5).and_hms(16, 0, 0),
end: Some(Utc.ymd(2008, 10, 5).and_hms(18, 0, 0)),
start: Utc.with_ymd_and_hms(2008, 10, 5, 16, 0, 0).unwrap(),
end: Some(Utc.with_ymd_and_hms(2008, 10, 5, 18, 0, 0).unwrap()),
note: Some("first line\nand a second line".into()),
},
];
let now = Utc.ymd(2008, 10, 5).and_hms(20, 0, 0);
let now = Utc.with_ymd_and_hms(2008, 10, 5, 20, 0, 0).unwrap();
let facts = Facts::new().with_now(now);
print_formatted(entries, &mut output, &facts, false).unwrap();
@ -330,13 +333,13 @@ mod tests {
Entry {
id: 1,
sheet: "default".into(),
start: Utc.ymd(2008, 10, 5).and_hms(16, 0, 0),
end: Some(Utc.ymd(2008, 10, 5).and_hms(18, 0, 0)),
start: Utc.with_ymd_and_hms(2008, 10, 5, 16, 0, 0).unwrap(),
end: Some(Utc.with_ymd_and_hms(2008, 10, 5, 18, 0, 0).unwrap()),
note: Some("quiúbole".into()),
},
];
let now = Utc.ymd(2008, 10, 5).and_hms(20, 0, 0);
let now = Utc.with_ymd_and_hms(2008, 10, 5, 20, 0, 0).unwrap();
let facts = Facts::new().with_now(now);
print_formatted(entries, &mut output, &facts, false).unwrap();
@ -359,20 +362,20 @@ mod tests {
Entry {
id: 1,
sheet: "sheet1".to_string(),
start: Utc.ymd(2008, 10, 5).and_hms(16, 0, 0),
end: Some(Utc.ymd(2008, 10, 5).and_hms(18, 0, 0)),
start: Utc.with_ymd_and_hms(2008, 10, 5, 16, 0, 0).unwrap(),
end: Some(Utc.with_ymd_and_hms(2008, 10, 5, 18, 0, 0).unwrap()),
note: Some("quiúbole".to_string()),
},
Entry {
id: 2,
sheet: "sheet2".to_string(),
start: Utc.ymd(2008, 10, 5).and_hms(16, 0, 0),
end: Some(Utc.ymd(2008, 10, 5).and_hms(18, 0, 0)),
start: Utc.with_ymd_and_hms(2008, 10, 5, 16, 0, 0).unwrap(),
end: Some(Utc.with_ymd_and_hms(2008, 10, 5, 18, 0, 0).unwrap()),
note: Some("quiúbole".to_string()),
},
];
let now = Utc.ymd(2008, 10, 5).and_hms(20, 0, 0);
let now = Utc.with_ymd_and_hms(2008, 10, 5, 20, 0, 0).unwrap();
let facts = Facts::new().with_now(now);
print_formatted(entries, &mut output, &facts, false).unwrap();

View File

@ -15,3 +15,4 @@ pub mod old;
pub mod interactive;
pub mod env;
pub mod io;
pub mod cli;

View File

@ -14,10 +14,8 @@ fn date_from_parts<T: TimeZone>(
timezone: T, input: &str, year: i32, month: u32, day: u32, hour: u32,
minute: u32, second: u32
) -> Result<DateTime<Utc>> {
let try_date = timezone.ymd_opt(
year, month, day
).and_hms_opt(
hour, minute, second
let try_date = timezone.with_ymd_and_hms(
year, month, day, hour, minute, second
);
match try_date {
@ -36,9 +34,9 @@ fn offset_from_parts(east: bool, hours: i32, minutes: i32) -> FixedOffset {
second += minutes * 60;
if east {
FixedOffset::east(second)
FixedOffset::east_opt(second).unwrap()
} else {
FixedOffset::west(second)
FixedOffset::west_opt(second).unwrap()
}
}
@ -163,54 +161,54 @@ pub fn parse_hours(input: &str) -> Result<u16> {
#[cfg(test)]
mod tests {
use chrono::{TimeZone, Duration};
use chrono::{TimeZone, Duration, Timelike};
use super::*;
#[test]
fn parse_datetime_string() {
assert_eq!(parse_time("2021-05-21 11:36").unwrap(), Local.ymd(2021, 5, 21).and_hms(11, 36, 0));
assert_eq!(parse_time("2021-05-21 11:36:12").unwrap(), Local.ymd(2021, 5, 21).and_hms(11, 36, 12));
assert_eq!(parse_time("2021-05-21 11:36").unwrap(), Local.with_ymd_and_hms(2021, 5, 21, 11, 36, 0).unwrap());
assert_eq!(parse_time("2021-05-21 11:36:12").unwrap(), Local.with_ymd_and_hms(2021, 5, 21, 11, 36, 12).unwrap());
assert_eq!(parse_time("2021-05-21T11:36").unwrap(), Local.ymd(2021, 5, 21).and_hms(11, 36, 0));
assert_eq!(parse_time("2021-05-21T11:36:12").unwrap(), Local.ymd(2021, 5, 21).and_hms(11, 36, 12));
assert_eq!(parse_time("2021-05-21T11:36").unwrap(), Local.with_ymd_and_hms(2021, 5, 21, 11, 36, 0).unwrap());
assert_eq!(parse_time("2021-05-21T11:36:12").unwrap(), Local.with_ymd_and_hms(2021, 5, 21, 11, 36, 12).unwrap());
}
#[test]
fn parse_date() {
assert_eq!(parse_time("2021-05-21").unwrap(), Local.ymd(2021, 5, 21).and_hms(0, 0, 0));
assert_eq!(parse_time("2021-05-21").unwrap(), Local.with_ymd_and_hms(2021, 5, 21, 0, 0, 0).unwrap());
}
#[test]
fn parse_hour() {
let localdate = Local::now().date();
let localdate = Local::now().with_hour(0).unwrap().with_minute(0).unwrap().with_second(0).unwrap().with_nanosecond(0).unwrap();
assert_eq!(parse_time("11:36").unwrap(), localdate.and_hms(11, 36, 0));
assert_eq!(parse_time("11:36:35").unwrap(), localdate.and_hms(11, 36, 35));
assert_eq!(parse_time("11:36").unwrap(), localdate.with_hour(11).unwrap().with_minute(36).unwrap().with_timezone(&Utc));
assert_eq!(parse_time("11:36:35").unwrap(), localdate.with_hour(11).unwrap().with_minute(36).unwrap().with_second(35).unwrap().with_timezone(&Utc));
}
#[test]
fn parse_hour_with_timezone() {
let hours: i32 = 3600;
let todayutc = Utc::now().date();
let todayutc = Utc::now().date_naive();
assert_eq!(parse_time("11:36Z").unwrap(), todayutc.and_hms(11, 36, 0));
assert_eq!(parse_time("11:36:35z").unwrap(), todayutc.and_hms(11, 36, 35));
assert_eq!(parse_time("11:36Z").unwrap(), todayutc.and_hms_opt(11, 36, 0).unwrap().and_local_timezone(Utc).unwrap());
assert_eq!(parse_time("11:36:35z").unwrap(), todayutc.and_hms_opt(11, 36, 35).unwrap().and_local_timezone(Utc).unwrap());
let offset = FixedOffset::west(5 * hours);
let todayoffset = offset.from_utc_datetime(&Utc::now().naive_utc()).date();
assert_eq!(parse_time("11:36-5:00").unwrap(), todayoffset.and_hms(11, 36, 0));
let offset = FixedOffset::west_opt(5 * hours).unwrap();
let today_at_offset = offset.from_utc_datetime(&Utc::now().naive_utc()).with_hour(0).unwrap().with_minute(0).unwrap().with_second(0).unwrap().with_nanosecond(0).unwrap();
assert_eq!(parse_time("11:36-5:00").unwrap(), today_at_offset.with_hour(11).unwrap().with_minute(36).unwrap().with_timezone(&Utc));
let offset = FixedOffset::east(5 * hours);
let todayoffset = offset.from_utc_datetime(&Utc::now().naive_utc()).date();
assert_eq!(parse_time("11:36:35+5:00").unwrap(), todayoffset.and_hms(11, 36, 35));
let offset = FixedOffset::east_opt(5 * hours).unwrap();
let today_at_offset = offset.from_utc_datetime(&Utc::now().naive_utc()).with_hour(0).unwrap().with_minute(0).unwrap().with_second(0).unwrap().with_nanosecond(0).unwrap();
assert_eq!(parse_time("11:36:35+5:00").unwrap(), today_at_offset.with_hour(11).unwrap().with_minute(36).unwrap().with_second(35).unwrap().with_timezone(&Utc));
}
#[test]
fn parse_with_specified_timezone() {
assert_eq!(parse_time("2021-05-21T11:36:12Z").unwrap(), Utc.ymd(2021, 5, 21).and_hms(11, 36, 12));
assert_eq!(parse_time("2021-05-21T11:36:12-3:00").unwrap(), Utc.ymd(2021, 5, 21).and_hms(14, 36, 12));
assert_eq!(parse_time("2021-05-21T11:36:12+3:00").unwrap(), Utc.ymd(2021, 5, 21).and_hms(8, 36, 12));
assert_eq!(parse_time("2021-05-21T11:36:12Z").unwrap(), Utc.with_ymd_and_hms(2021, 5, 21, 11, 36, 12).unwrap());
assert_eq!(parse_time("2021-05-21T11:36:12-3:00").unwrap(), Utc.with_ymd_and_hms(2021, 5, 21, 14, 36, 12).unwrap());
assert_eq!(parse_time("2021-05-21T11:36:12+3:00").unwrap(), Utc.with_ymd_and_hms(2021, 5, 21, 8, 36, 12).unwrap());
}
fn time_diff(t1: DateTime<Utc>, t2: DateTime<Local>) {