Natural-language compatibility review
This review covers the supplied English/French examples and all eight edtfy test files, including its disabled shared-component collection examples. Selected edtfy examples are credited to Nicolas Barbotte (MIT). We use the examples to identify syntax gaps; their older EDTF outputs are not a conformance oracle.
The tables are generated by node packages/natural/scripts/generate-compatibility.cjs. The phrase expectations live in packages/natural/tests/fixtures/compatibility.json and are enforced by compatibility.test.ts. English numeric examples use en-US, French uses fr-FR, and rolling short years use January 1, 2026. All alternatives are checked, in confidence order. Separate shared fixtures and round-trip tests cover Spanish and all six regional locale presets.
Corrected patterns
- A known day survives an unspecified month:
1870-XX-12renders as 12th of unknown month, 1870, día 12 de mes desconocido, 1870, or 12 d'un mois inconnu, 1870. These phrases parse back without losing the day. - Dates and seasons share interval endpoints: march 1988 - spring 1990 becomes
1988-03/1990-21. This is a supported extension, excluded by the optional strict interoperability profile. Reversed intervals are rejected. Season calendar bounds remain application conventions. - French De … à …, articles, and apostrophe contractions work with shared date semantics. Season qualifiers work before or after the season. Century-wide qualifiers apply to both boundaries.
- Missing-year forms, semicolon lists, short range end years, ordinal/roman centuries, selected abbreviations, and validated weekday prefixes have regression coverage. January 12 produces only
XXXX-01-12; January 0012 selects the historical month/year.
Modern EDTF distinctions
The current LOC specification replaced u with X, combined ?~ into %, and replaced interval keywords with empty/.. endpoints. We do not accept obsolete literal spellings as modern EDTF.
Since 1970 means 1970/..; an unknown end is 1970/ and renders explicitly as unknown. 20th century means 1901/2000, whereas 19XX covers 1900–1999. January 1999 to December 1999 is an interval, not a synonym for the unspecified month 1999-XX. 2020; 2021 is an inclusive list, {2020,2021}; bare 2020,2021 is not valid EDTF. Strict event-date cutoffs use sets and exclude the cutoff unit. Fuzzy cutoff phrases remain errors.
Bare one- or two-digit years require an era marker or four-digit spelling: write 90 CE or 0090 for year 90. Write 1990 explicitly or use '90 for the rolling window. Short end years in a range inherit the start century, advancing to the next century if necessary: 1851-52 → 1851/1852. Valid literal EDTF takes precedence: 1851-12 remains December 1851.
Preferred rendering equivalents
These are our preferred phrases for the valid modern equivalents of the supplied rendering examples. Exact wording and capitalization may differ; tests check the meaning after parsing the preferred rendering. Storage should retain EDTF, because display options can suppress qualifiers or eras.
| EDTF | English | French | Spanish |
|---|---|---|---|
1975-07-01 | July 1, 1975 | 1 juillet 1975 | 1 de julio de 1975 |
1975? | 1975 (uncertain) | 1975 (incertain) | 1975 (incierto) |
1975-22 | Summer 1975 | été 1975 | verano 1975 |
199X | 1990s | Les années 1990 | Los años 1990 |
19XX | 1900s | 19XX | 19XX |
1970/1980 | 1970 to 1980 | 1970 à 1980 | 1970 a 1980 |
1970/.. | 1970 to open end | 1970 à fin ouverte | 1970 a fin abierto |
1970/ | 1970 to unknown | 1970 à inconnu | 1970 a desconocido |
1970~/1980~ | 1970 (approximate) to 1980 (approximate) | 1970 (approximatif) à 1980 (approximatif) | 1970 (aproximado) a 1980 (aproximado) |
1999-XX | some month in 1999 | un mois de 1999 | algún mes de 1999 |
{2020,2021} | All of: 2020, 2021 | Toutes ces dates: 2020 et 2021 | Todas estas fechas: 2020 y 2021 |
1870-XX-12 | 12th of unknown month, 1870 | 12 d'un mois inconnu, 1870 | día 12 de mes desconocido, 1870 |
Phrase-by-phrase results
| Locale | Input | EDTF candidates / decision | Explanation / source |
|---|---|---|---|
| en-US | July 1, 1975 | 1975-07-01 | |
| en-US | 1975? | 1975? | |
| en-US | summer 1975 | 1975-22 | |
| en-US | 1990s | 199X | |
| en-US | 20th century | 1901/2000 | Numbered centuries use historical boundaries; 19XX covers 1900–1999 instead. |
| en-US | 1970 to 1980 | 1970/1980 | |
| en-US | since 1970 | 1970/.. | An open endpoint is distinct from the unknown endpoint in 1970/. |
| en-US | circa 1970 to circa 1980 | 1970~/1980~ | |
| en-US | January 1999 to December 1999 | 1999-01/1999-12 | An explicit interval is not the unspecified month 1999-XX. |
| en-US | 2020; 2021 | {2020,2021} | An inclusive list uses braces; adjacent years compact. |
| en-US | January 12, 1940 | 1940-01-12 | |
| en-US | 90 | Rejected | A bare one- or two-digit year requires an era marker or four-digit spelling. |
| en-US | '90 | 1990 | |
| en-US | January 2008 | 2008-01 | |
| en-US | the year 1800 | 1800 | |
| en-US | 10/7/2008 | 2008-10-07; 2008-07-10 | US ordering ranks first; both valid interpretations survive. |
| en-US | 1860? | 1860? | |
| en-US | 1862 (uncertain) | 1862? | |
| en-US | circa Feb 1812 | 1812-02~ | |
| en-US | c.1860 | 1860~ | |
| en-US | ca1860 | 1860~ | |
| en-US | approx 1860 | 1860~ | |
| en-US | ca. 1860s | 186X~ | |
| en-US | circa 1840s | 184X~ | |
| en-US | ca. 1860s? | 186X% | Modern EDTF combines uncertainty and approximation as %. |
| en-US | c1800s? | 18XX%; 180X% | Both century-block and decade readings remain ambiguous; a qualifier does not disambiguate them. |
| en-US | January 12 | XXXX-01-12 | A month and day without a year. Write January 0012 for the historical year. |
| en-US | January | XXXX-01 | |
| en-US | 7/2008 | 2008-07 | |
| en-US | month in 1872 | 1872-XX | |
| en-US | day in January 1872 | 1872-01-XX | |
| en-US | day in 1872 | 1872-XX-XX | |
| en-US | Autumn 1872 | 1872-23 | |
| en-US | Fall 1872 | 1872-23 | |
| en-US | earlier than 1928 | [..1927] | Strict event-date cutoff excludes 1928; it is a date-choice set. |
| en-US | later than 1928 | [1929..] | Strict event-date cutoff excludes 1928. |
| en-US | before January 1928 | [..1927-12] | Strict cutoff shifts one month. |
| en-US | after about the 1920s | Rejected | A fuzzy cutoff has no exact exclusive boundary; use an exact cutoff or literal EDTF with the intended meaning. |
| en-US | 1st century | 0001/0100 | Historical century boundaries differ from 00XX. |
| en-US | 10c | 0901/1000 | |
| en-US | 19th century? | 1801?/1900? | The qualification applies to both boundaries of the century. |
| en-US | a day in about Spring 1849? | Rejected | EDTF has no day component on a season: 1849-21-XX is invalid. Use circa Spring 1849? (1849-21%) if season precision is sufficient, or specify calendar dates. |
| en-US | 1851-1852 | 1851/1852 | |
| en-US | 1851-1852; printed 1853-1854 | Rejected | Bibliographic event annotations are not date syntax. The parser rejects the whole input instead of discarding the printing date. |
| en-US | 1851-52 | 1851/1852 | |
| en-US | 1856-ca. 1865 | 1856/1865~ | |
| en-US | 1860s-1870s | 1860/1879 | Interval endpoints expand the decade start/end according to the existing parsing convention. |
| en-US | 1920s - early 1930s | 1920/1933 | The early-decade convention retains the explicit early modifier. |
| en-US | 1938, printed 1940s-1950s | Rejected | No silent truncation of annotated prose; parse each intended event separately. |
| en-US | 12th of unknown month, 1870 | 1870-XX-12 | |
| en-US | march 1988 - spring 1990 | 1988-03/1990-21 | |
| fr-FR | 1 Juillet 1975 | 1975-07-01 | |
| fr-FR | 1975? | 1975? | |
| fr-FR | été 1975 | 1975-22 | |
| fr-FR | Les années 1990 | 199X | |
| fr-FR | 20e siècle | 1901/2000 | Numbered centuries are not equivalent to 19XX. |
| fr-FR | De 1970 à 1980 | 1970/1980 | |
| fr-FR | Depuis 1970 | 1970/.. | Open, not unknown, end. |
| fr-FR | De 1970 environ à 1980 environ | 1970~/1980~ | |
| fr-FR | De Janvier 1999 à Décembre 1999 | 1999-01/1999-12 | Preserves explicit interval phrasing. |
| fr-FR | 2020; 2021 | {2020,2021} | |
| en-US | mar the 29 1988 | 1988-03-29 | edtfy test |
| en-US | bet the 03/28/1988 and the 03/30/1988 | 1988-03-28/1988-03-30 | edtfy test |
| fr-FR | le 29 mar 1988 | 1988-03-29 | edtfy test |
| fr-FR | du 28 mars 1988 au 30/03/1988 | 1988-03-28/1988-03-30 | edtfy test |
| en-US | monday 03/29/1988 | Rejected | March 29, 1988 was Tuesday; weekdays must match. edtfy test |
| fr-FR | jeudi 29/03/1988 | Rejected | The weekday contradicts the date. edtfy test |
| en-US | from sep 1988 to 04/30/1988 | Rejected | Reversed intervals are invalid. edtfy test |
| en-US | march 1988 - winter 2005? | 1988-03/2005-24? | edtfy test |
| en-US | from around sep 10 1988? to unknown | 1988-09-10%/ | edtfy test |
| fr-FR | environ l'hiver 1988? | 1988-24% | edtfy test |
| fr-FR | 1988 - en cours | 1988/.. | edtfy test |
| en-US | XIXth century | 1801/1900 | edtfy test |
| fr-FR | XVIIIème siècle | 1701/1800 | edtfy test |
| fr-FR | IV siecle | 0301/0400 | edtfy test |
| fr-FR | 2nd siècle après JC | 0101/0200 | edtfy test |
| en-US | 12th March 24BC | -0023-03-12 | edtfy test |
| fr-FR | printemps 4AEC | -0003-21 | edtfy test |
| en-US | bf. 1988 | [..1987] | edtfy test |
| fr-FR | ap. 1988 | [1989..] | edtfy test |
| en-US | <1988 | [..1987] | edtfy test |
| fr-FR | >1988 | [1989..] | edtfy test |
| en-US | 198u | Rejected | Legacy u masks are not modern EDTF. Use 198X. edtfy test |
| fr-FR | 11/0u/1988 | Rejected | Legacy slash masks are intentionally unsupported. Use modern EDTF 1988-0X-11. edtfy test |
| en-US | 11/10/21988 | Rejected | The selected EDTF profile supports extended years as year-only values, not extended full calendar dates. edtfy test |
Remaining scope differences
The upstream tests include incorrect weekdays and reversed intervals; we reject them. Weekday prefixes constrain the full calendar date instead of being discarded. Draft u/* slash masks should be converted explicitly to modern EDTF with X; extended years remain year-only in the selected profile.
Shared-component collection syntax such as spring or summer 2015 and April 1 or 2 2015 remains outside this change (these cases are disabled in edtfy's suites). Use explicit members, such as One of: spring 2015, summer 2015 or One of: April 1, 2015, April 2, 2015. A future extension needs contextual component propagation through all collection members and language-specific word order, rather than guessing a year from the last number.
Bibliographic event labels such as printed are not discarded. Parse each event separately so dates and event roles are retained. A day within an approximate season cannot be encoded by appending -XX to a season code; use season precision if sufficient, or explicit calendar dates. No broad text-stripping or obsolete-EDTF compatibility mode was added.