Conversation
…ng, closed #94 (proleptic Gregorian, in which a year zero exists and equals 1 BCE)
There was a problem hiding this comment.
Pull request overview
This PR releases messydates v1.1.0 and aligns BCE/CE parsing with ISO 8601-2 astronomical year numbering (including year 0000 = 1 BCE), fixing the historical off-by-one conversion described in #94 and ensuring sequences/expansions traverse year zero.
Changes:
- Convert historical
N BC/BCEprose to astronomical year numbering (N BCE -> -(N-1)), preserving signed ISO years as already-astronomical. - Update sequencing logic to rely on
Datearithmetic across BCE/CE (including year 0000), removing BCE-era special-casing. - Refresh tests and documentation (README, Rd, NEWS) to reflect the corrected conversion and leap-year expectations.
Reviewed changes
Copilot reviewed 14 out of 18 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/testthat/test-convert_sequence.R | Updates BCE/CE boundary sequence expectations to include astronomical year 0000. |
| tests/testthat/test-convert_expand.R | Adjusts expansion day counts for BCE years under astronomical numbering. |
| tests/testthat/test-coerce_to.R | Updates coercion test expectations for historical BCE prose sets. |
| tests/testthat/test-coerce_resolve.R | Updates resolve expectations for BCE month ranges after conversion fix. |
| tests/testthat/test-coerce_from.R | Updates Roman-date parsing expectations for “44 BC” -> “-0043-…”. |
| tests/testthat/test-class_create.R | Updates BCE coercion and printing expectations for corrected astronomical mapping. |
| README.Rmd | Updates documentation examples to reflect corrected BC->astronomical conversion. |
| README.md | Updates rendered README examples/tables for corrected astronomical years. |
| R/operate_statements.R | Clarifies is_bce() semantics with astronomical numbering (year 0000 not negative). |
| R/convert_sequence.R | Simplifies sequencing across BCE/CE by using Date sequencing + zero_padding(). |
| R/coerce_to_messydate.R | Implements historical->astronomical conversion and preserves year 0000 (not “unspecified”). |
| R/coerce_from_messydate.R | Documents difference between historical “1000 BC” and signed ISO “-1000”. |
| NEWS.md | Adds v1.1.0 release notes describing BCE/CE/year-zero changes and #94 fix. |
| man/operate_statements.Rd | Syncs man page with updated is_bce() documentation. |
| man/convert_sequence.Rd | Syncs man page with year-zero traversal behavior in sequences. |
| man/coerce_to.Rd | Adds “Eras and year numbering” documentation and updates examples. |
| man/coerce_from.Rd | Syncs man page examples about historical vs signed ISO BCE years. |
| DESCRIPTION | Bumps package version to 1.1.0. |
Files not reviewed (4)
- man/coerce_from.Rd: Generated file
- man/coerce_to.Rd: Generated file
- man/convert_sequence.Rd: Generated file
- man/operate_statements.Rd: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| st_negative <- function(dates) { | ||
| dates <- stringi::stri_replace_all_regex(dates, "(BCE|Bce|bce|bc|BC|Bc|bC)", "") | ||
| dates <- stringi::stri_trim_both(dates) | ||
| dates <- paste0("-", dates) | ||
| .hist_to_astro(dates) | ||
| } |
…ow reports what could not be parsed
…"all members of")
…hat they contained
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #95 +/- ##
==========================================
+ Coverage 90.41% 91.00% +0.59%
==========================================
Files 18 19 +1
Lines 1502 1679 +177
==========================================
+ Hits 1358 1528 +170
- Misses 144 151 +7 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Description
Package
.github/CONTRIBUTING.mdsothat human contributors and coding agents read the same notes
DESCRIPTIONversion is bumped, that the PR title names the new version, andthat the PR description itemizes changes under subsection titles; these items
are consequently dropped from the pull request template
Config/Needs/checkpackages insteadof
Config/Needs/websiteClass
validate_messydate()to report which elements failed and what theycontained, instead of naming only the rule that was broken
somewhere in it happened to contain a digit
mdatewith[<-or[[<-nowreports what could not be parsed, rather than silently blanking the element
unique()andduplicated()methods formdateobjects (closesunique()drops themdateclass #106)unique()fell through to the character method and dropped theclass, so a deduplicated column silently stopped being an
mdateso
"2012-01"and"2012-01-01..2012-01-31"remain distinctCoercion
as_messydate()to validate its input rather than carrying values itcannot interpret:
"2019-02-30","2019-06-31"and"2019-01-01 25:00"now error instead of being acceptedas written; relatedly,
"2019-13-45"is no longer silently reordered into"2019-45-13", since month and day are only swapped where the swap yieldsa date that could exist
{messydates}does not represent (week dates,ordinal dates, season codes, significant digits, extended years, the
P-style duration notation, and repeating intervals) now error naming theformat, instead of passing through as strings that nothing downstream could
expand, resolve or compare. Durations themselves are unaffected: they are
written as date ranges and handled by
mduration, and the error for"P1Y2M"points thereNA, but now warns, listing whatcould not be read
md_problems(), which reports one row per unparseable element of avector, with the reason for each, for checking a column of dates before
coercing it
as_messydate()methods for factors (coerced via their labels, thecommon case when a column was read in with
stringsAsFactors = TRUE) and adefault method that names the offending class rather than failing with R's
UseMethodmessage"July 4 1976"previously lost its day wheneveranother value shared the vector with it
[]sets ("one member of") silently rewrote as{}sets ("all members of").[]its own meaning in the resolution functions remains outstandingto convert to ISO 8601-2 astronomical year numbering
(proleptic Gregorian, in which a year zero exists and equals 1 BCE):
N BCEmaps to the astronomical year-(N-1), so"44 BC"becomes
-0043and"1 BC"becomes0000(year zero); a signed ISO yearsuch as
"-0044"is already astronomical and is left unchanged0000was misread as anunspecified year) and is traversed by
seq()andexpand(), so a sequencespanning the BCE/CE boundary now passes through the whole of year
0000rather than jumping from
-0001straight to0001separately, rather than by counting how many markers a string contains
(they are, as before, always removed in the parsed
mdate, which recordsthe era in the sign of the year alone). So an input marker written once at
the end of a range or set applies to every bound of it:
"..200 BC","200..100 BC"and"44, 33 BC"now give..-199,-0199..-0099and{-0043,-0032}, where previously the non-leading bounds silently stayedCE; an input marker written before a date still governs that date, so
"{BC2010-10-10,BC2010-10-11}"gives{-2009-10-10,-2009-10-11}; and"200 BC..100 AD"spans the two eras, giving-0199..0100given in prose, so
"circa 200 BC"is now~-199rather than0200~Expand/Contract
expand()handles unspecified years"192X"raised'from' must be a finite numberand"18XX"silently returned a single date,even though these are what the prose parser produces for decades and centuries
"192X"gives everyday of the 1920s)
year (
"192X-05-04"gives ten dates, not nine years of them)-1999being earlierthan
-1900"XXXX", refused with a messagesuggesting
vmin()/vmax()expand()applies unspecified-component rules to each member of a setseparately, fixing over-expansion of sets whose members had an unspecified
month:
"{2008-XX-31,2009-XX-31}"gave 671 dates and now gives 24contract()returning every set in{}notation, so that a[]setno longer became a
{}set on a round-trip throughexpand()/contract()(closes Give
[]sets their own meaning in the resolution functions #99)contract()is given anmdate, since a list of datesdoes not record which kind of set its members came from
established that both should continue to expand to the same members (closes Give
[]sets their own meaning in the resolution functions #99):?resolve_tendencynow distinguishes a central tendency that describeswhere several recorded occurrences sit (
{}) from one that is a pointestimate of a single unknown date (
[]), as for a range?operate_setand?operate_proportionalnow note that a result for a[]set reads as the candidates that remain possible, or the probabilitythat a comparison holds, rather than a share of recorded occurrences
Checklist: