Skip to content

Commit

Permalink
Merge pull request #111 from jwodder/gh-100
Browse files Browse the repository at this point in the history
Split into workspace
  • Loading branch information
jwodder authored Dec 19, 2024
2 parents 684e152 + 4f2bb68 commit 2f96bbc
Show file tree
Hide file tree
Showing 40 changed files with 353 additions and 228 deletions.
20 changes: 10 additions & 10 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ jobs:
uses: taiki-e/install-action@cargo-hack

- name: Build crate
run: cargo hack --feature-powerset --exclude-features gentests build --all-targets --verbose
run: cargo hack --workspace --exclude gentests --feature-powerset build --all-targets --verbose

- name: Test crate
run: cargo hack --feature-powerset --exclude-features gentests test --verbose
run: cargo hack --workspace --exclude gentests --feature-powerset --exclude-features gentests test --verbose

minimal-versions:
runs-on: ubuntu-latest
Expand All @@ -91,10 +91,10 @@ jobs:
tool: cargo-hack,cargo-minimal-versions

- name: Build crate
run: cargo minimal-versions --direct --feature-powerset --exclude-features=gentests build --all-targets --verbose
run: cargo minimal-versions --direct --workspace --exclude=gentests --feature-powerset build --all-targets --verbose

- name: Test crate
run: cargo minimal-versions --direct --feature-powerset --exclude-features=gentests test --verbose
run: cargo minimal-versions --direct --workspace --exclude=gentests --feature-powerset test --verbose

coverage:
# This is separate from the main tests because cargo-llvm-cov doesn't run
Expand All @@ -120,7 +120,7 @@ jobs:
tool: cargo-llvm-cov

- name: Test with coverage
run: cargo llvm-cov --all-features --lcov --output-path lcov.info
run: cargo llvm-cov --workspace --all-features --lcov --output-path lcov.info

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
Expand Down Expand Up @@ -149,10 +149,10 @@ jobs:
uses: taiki-e/install-action@cargo-hack

- name: Check code
run: cargo hack --feature-powerset clippy --all-targets -- -Dwarnings
run: cargo hack --workspace --feature-powerset clippy --all-targets -- -Dwarnings

- name: Check formatting
run: cargo fmt --check
run: cargo fmt --all --check

docs:
runs-on: ubuntu-latest
Expand All @@ -170,7 +170,7 @@ jobs:
uses: Swatinem/rust-cache@v2

- name: Check docs
run: cargo doc --no-deps --all-features
run: cargo doc -p julian --no-deps --all-features
env:
RUSTDOCFLAGS: -Dwarnings

Expand All @@ -191,8 +191,8 @@ jobs:

- name: Run gentests
run: |
cargo build --bin gentests --features gentests --verbose
cargo run --bin gentests --features gentests
cargo build -p gentests --verbose
cargo run -p gentests
- name: Check that autogenerated tests were not modified
run: git --no-pager diff --exit-code
Expand Down
23 changes: 19 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 8 additions & 43 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,50 +1,15 @@
[package]
name = "julian"
version = "0.6.0-dev"
[workspace]
members = ["crates/*"]
resolver = "2"

[workspace.package]
edition = "2021"
rust-version = "1.67"
description = "Convert between Julian day numbers and Julian & Gregorian calendars"
authors = ["John Thorvald Wodder II <julian-rs@varonathe.org>"]
repository = "https://github.com/jwodder/julian-rs"
license = "MIT"
keywords = ["calendar", "gregorian-calendar", "julian-calendar", "julian-day"]
categories = ["date-and-time"]
exclude = ["/.*"]
default-run = "julian"

[dependencies]
anyhow = { version = "1.0.82", optional = true }
chrono = { version = "0.4.38", optional = true, default-features = false }
csv = { version = "1.3.0", optional = true }
lexopt = { version = "0.3.0", optional = true }
serde = { version = "1.0.200", features = ["derive"], optional = true }
thiserror = "2.0.0"

[dev-dependencies]
assert_matches = "1.5.0"
indoc = "2.0.5"
rstest = { version = "0.23.0", default-features = false }
rstest_reuse = "0.7.0"

[features]
default = ["cli"]
chrono = ["dep:chrono"]
cli = ["dep:lexopt"]
gentests = ["dep:anyhow", "dep:csv", "dep:serde"]

[[bin]]
name = "gentests"
required-features = ["gentests"]

[[bin]]
name = "julian"
required-features = ["cli"]

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[lints.rust]
[workspace.lints.rust]
# Lint groups:
future_incompatible = { level = "deny", priority = -1 }
refining_impl_trait = { level = "deny", priority = -1 }
Expand Down Expand Up @@ -123,7 +88,7 @@ unused_comparisons = "deny"
useless_ptr_null_checks = "deny"
while_true = "deny"

[lints.rustdoc]
[workspace.lints.rustdoc]
bare_urls = "deny"
broken_intra_doc_links = "deny"
invalid_codeblock_attributes = "deny"
Expand All @@ -133,7 +98,7 @@ private_intra_doc_links = "deny"
redundant_explicit_links = "deny"
unescaped_backticks = "deny"

[lints.clippy]
[workspace.lints.clippy]
# Deny all warn-by-default lints:
all = { level = "deny", priority = -1 }

Expand Down
179 changes: 18 additions & 161 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,169 +4,26 @@
[![Minimum Supported Rust Version](https://img.shields.io/badge/MSRV-1.67-orange)](https://www.rust-lang.org)
[![MIT License](https://img.shields.io/github/license/jwodder/julian-rs.svg)](https://opensource.org/licenses/MIT)

[GitHub](https://github.com/jwodder/julian-rs) | [crates.io](https://crates.io/crates/julian) | [Documentation](https://docs.rs/julian) | [Issues](https://github.com/jwodder/julian-rs/issues) | [Changelog](https://github.com/jwodder/julian-rs/blob/master/CHANGELOG.md)
This is a Rust [workspace][] containing various packages for converting between
[Julian day numbers][] and dates in the [Gregorian calendar][] (either
proleptic or with the Reformation occurring at a given date) and/or the
proleptic [Julian calendar][].

`julian` is a Rust library for converting between [Julian day numbers][] and
dates in the [Gregorian calendar][] (either proleptic or with the Reformation
occurring at a given date) and/or the proleptic [Julian calendar][]. There are
also features for querying details about years & months in a "reforming"
Gregorian calendar and how they are affected by the calendar reformation date
of your choice.
The packages are:

[Julian day numbers]: https://en.wikipedia.org/wiki/Julian_day
[Gregorian calendar]: https://en.wikipedia.org/wiki/Gregorian_calendar
[Julian calendar]: https://en.wikipedia.org/wiki/Julian_calendar

Examples
========

Before you construct a date, you must first choose a calendar in which to
reckon dates. `Calendar::GREGORIAN` is the proleptic Gregorian calendar, which
should be both simple and useful enough for most basic purposes.

To convert a Julian day number to a date in a calendar, use the
`Calendar::at_jdn()` method, like so:

```rust
use julian::{Calendar, Month};

let cal = Calendar::GREGORIAN;
let date = cal.at_jdn(2460065);
assert_eq!(date.year(), 2023);
assert_eq!(date.month(), Month::April);
assert_eq!(date.day(), 30);
```

So JDN 2460065 is April 30, 2023, in the proleptic Gregorian calendar.

To convert a date to a Julian day number, use `Calendar::at_ymd()` to construct
the date, and then call its `julian_day_number()` method:

```rust
use julian::{Calendar, Month};

let cal = Calendar::GREGORIAN;
let date = cal.at_ymd(2023, Month::April, 30).unwrap();
assert_eq!(date.julian_day_number(), 2460065);
```

See [the documentation](https://docs.rs/julian) for more things you can do!

Command
=======

`julian` also provides a command of the same name for converting between Julian
day numbers and dates in Julian-style calendars. To install this command on
your system, run:

cargo install julian

Usage
-----

```text
julian [<options>] [<date> ...]
```

When invoked without arguments, the `julian` command displays the current date
in the proleptic Gregorian calendar & UTC timezone along with the corresponding
Julian day number.

When `julian` is invoked with one or more arguments, any calendar date
arguments (in the form "YYYY-MM-DD" or "YYYY-JJJ") are converted to Julian day
numbers, and any integer arguments are treated as Julian day numbers and
converted to calendar dates. By default, dates are read & written using the
proleptic Gregorian calendar, but this can be changed with the `--julian` or
`--reformation` option.
- [`julian`][] — Rust library for converting between Julian day numbers and
Julian & Gregorian calendars

`julian` uses [astronomical year numbering][yzero], where 1 BC (the year
immediately before AD 1) is denoted on input & output as year 0 (displayed as
"0000"), and the year before that (normally called 2 BC) is denoted -1
(displayed as "-0001"). In addition, the start of the year is always taken as
being on January 1, even though [not all users of the Julian calendar
throughout history have followed this convention][NYD].
- [`julian-cli`][] — CLI command for converting between Julian day numbers and
Julian & Gregorian calendars

Options
-------
- [`gentests`][] — Internal package for use in generating test code for
`julian`

- `-c`, `--countries` — List the country codes recognized by the
`-r`/`--reformation` option. The output is a table with the following
columns:

- "Code" — the two-letter country code accepted by `--reformation`
- "Country" — the country's English name (or a common variation thereof)
- "Reformation" — the Julian day number of the date on which the country
first observed the Gregorian calendar
- "Last Julian" — the Old Style calendar date of the day before the
reformation
- "First Gregorian" — the New Style calendar date of the day of the
reformation

The database of country reformations dates is drawn from [the Debian
version of `ncal.c` as of 2023-04-26][src], so blame Debian for any
historical inaccuracies.

- `-h`, `--help` — Display a summary of the command-line options and exit

- `-j`, `--julian` — Read & write dates using the proleptic Julian calendar

- `-J`, `--json` — Output JSON. See [JSON Output](#json-output) below for more
information.

- `-o`, `--ordinal` — Output calendar dates in the form "YYYY-JJJ", where the
part after the hyphen is the day of the year from 001 to 366 (the ordinal
date)

- `-q`, `--quiet` — Do not print the input value before each output value. Do
not print "JDN" before Julian day numbers.

- `-r <jdn>`, `--reformation <jdn>` — Read & write dates using a reforming
calendar in which the Gregorian calendar is first observed on the date with
the given Julian day number

A two-letter country code (case insensitive) may be given in place of a JDN
in order to use the calendar reformation as it was observed in that
country. Run `julian --countries` to get a list of recognized country
codes and their corresponding dates.

- `-s`, `--style` — Mark dates in reforming calendars as "O.S." (Old Style) or
"N.S." (New Style)". Has no effect when `-r`/`--reformation` is not given or
when `-o`/`--ordinal` is given.

- `-V`, `--version` — Show the program version and exit

[yzero]: https://en.wikipedia.org/wiki/Astronomical_year_numbering
[NYD]: https://en.wikipedia.org/wiki/Julian_calendar#New_Year's_Day
[src]: https://salsa.debian.org/meskes/bsdmainutils/-/blob/70ff77b0f084de4a14d79bed935e1958020f43dc/usr.bin/ncal/ncal.c

JSON Output
-----------

When `julian` is invoked with the `-J`/`--json` option, it outputs a JSON
breakdown of the chosen calendar and input & output values. The output
structure is an object with two keys, `"calendar"` and `"dates"`.

- `"calendar"` — Denotes the type of calendar selected for the `julian`
invocation. This is an object that always contains at least one key,
`"type"`, the value of which is `"gregorian"` (for the default proleptic
Gregorian calendar), `"julian"` (for the proleptic Julian calendar), or
`"reforming"` (for a reforming calendar). When `"type"` is `"reforming"`,
there will be an additional field, `"reformation"`, whose value is the Julian
day number of the date on which the calendar first follows the Gregorian
calendar.

- `"dates"` — A list of objects, one per argument (or, if no arguments were
given, one object for the current date). Each object contains the following
fields describing the date indicated by the argument, regardless of whether
the argument was a calendar date or a Julian day number:

- `"julian_day_number"` — the date's Julian day number
- `"year"` — the date's year
- `"month"` — the number (1-12) of the date's month
- `"day"` — the date's day-of-month (1-31)
- `"ordinal"` — the date's one-based day-of-year ordinal (1-366)
- `"display"` — the date in "YYYY-MM-DD" form
- `"ordinal_display"` — the date in "YYYY-JJJ" form
- `"old_style"` — This field is only present if the calendar in use is a
reforming calendar. It is `true` if the date occurs before the calendar
reformation, `false` otherwise.
[workspace]: https://doc.rust-lang.org/cargo/reference/workspaces.html
[Julian day numbers]: https://en.wikipedia.org/wiki/Julian_day
[Gregorian calendar]: https://en.wikipedia.org/wiki/Gregorian_calendar
[Julian calendar]: https://en.wikipedia.org/wiki/Julian_calendar
[`julian`]: https://github.com/jwodder/julian-rs/tree/master/crates/julian
[`julian-cli`]: https://github.com/jwodder/julian-rs/tree/master/crates/julian-cli
[`gentests`]: https://github.com/jwodder/julian-rs/tree/master/crates/gentests
18 changes: 18 additions & 0 deletions crates/gentests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "gentests"
version = "0.0.0"
edition.workspace = true
rust-version.workspace = true
description = "Generate test code for julian crate"
authors.workspace = true
repository.workspace = true
license.workspace = true
publish = false

[dependencies]
anyhow = "1.0.82"
csv = "1.3.0"
serde = { version = "1.0.200", features = ["derive"] }

[lints]
workspace = true
1 change: 1 addition & 0 deletions crates/gentests/LICENSE
Loading

0 comments on commit 2f96bbc

Please sign in to comment.