1.2025.5 < 1.20250323.0 < 2.2025.0 < 2.202503.1 < 2.20250125.1
Purpose & Core Concept
ScalVer is a calendar-aware, SemVer-compatible and extendable versioning scheme expressed as
<MAJOR>.<DATE>.<PATCH> where the DATE segment may
lengthen over time within a MAJOR line:
YYYY β YYYYMM β YYYYMMDD (YYYY[MM[DD]])
<MAJOR>β mirrors SemVer's MAJOR component; incremented for breaking-change releases or whenever theDATEsegment would otherwise need to contract.<DATE>β expressed asYYYY,YYYYMM, orYYYYMMDDin UTC; it may stay the same width or expand (year β month β day) as release cadence accelerates, and it resets to its initial width when the next MAJOR version begins.<PATCH>β mirrors SemVer's PATCH component; a monotonically increasing counter for backward-compatible updates released within the sameDATEwindow.
Motivation
ScalVer provides the time-based clarity of CalVer (knowing when something was released) while needing the compatibility guarantees and tooling support of SemVer (knowing if an update breaks things).
- Adjustable cadence : ScalVer allows projects to adjust their release frequency (yearly, monthly, daily) and reflect this in the versioning without breaking the logical version order.
- SemVer Compatibility: every ScalVer tag is syntactically valid SemVer, so existing tooling (CI/CD, package managers, release dashboards) works unchanged.
Segments & Core Rules
| Segment | SemVer Equivalent | ScalVer Behaviour |
|---|---|---|
| MAJOR | MAJOR | Bump for breaking changes or when DATE would otherwise shrink |
| DATE | MINOR | May stay the same length or grow from YYYY β YYYYMM β
YYYYMMDD
|
| PATCH | PATCH | Increment for safe, backward-compatible releases within the same DATE |
SemVer 2.0 Compatible: Each ScalVer tag is a syntactically valid SemVer 2.0
version; the date sits in the position that vanilla SemVer calls βMINORβ, so standard parsers
(golang.org/x/mod/semver, npm-semver, Python packaging.version,
Maven's ComparableVersion, Cargo, etc.) order ScalVer releases correctly without
modificationΒΉ
Date-Only-Grows (DOG): within any single MAJOR line the DATE can stay the same length or grow, but never shrink.
ΒΉY10K note: ScalVer's ordering logic continues to work for years beyond 9999. The reference grammar intentionally limits YYYY to four digits for ISO-8601 clarity and broad tooling support, but the scheme is formally 100% compatible with longer year fields and can be widened whenever ecosystems catch up.
Difference with SemVer Backus-Naur Form Grammar
--- SemVer2.0.bnf +++ SemVer2.0.bnf @@ -<version core> ::= <major> "." <minor> "." <patch> +<version core> ::= <major> "." <date> "." <patch> @@ -<minor> ::= <numeric identifier> + +<date> ::= <year> + | <year> <month> + | <year> <month> <day> + +<year> ::= <positive digit> <digit> <digit> <digit> +<month> ::= "01" | "02" | "03" | "04" | "05" | "06" + | "07" | "08" | "09" | "10" | "11" | "12" +<day> ::= "01" | "02" | "03" | "04" | "05" | "06" | "07" | "08" | "09" + | "10" | "11" | "12" | "13" | "14" | "15" | "16" | "17" | "18" | "19" + | "20" | "21" | "22" | "23" | "24" | "25" | "26" | "27" | "28" | "29" + | "30" | "31"
Full ScalVer BNF Grammar
The complete ScalVer grammar is available in the BNF file for reference and implementation.
Release-Cadence Examples
| Cadence | Example tag | Meaning |
|---|---|---|
| Yearly | 0.2025.0 |
First 2025 alpha |
| Yearly | 1.2025.0 |
First 2025 stable release |
| Yearly | 1.2025.3 |
Fourth 2025 patch |
| Monthly | 1.202503.0 |
First March 2025 release |
| Monthly | 1.202503.2 |
Third March 2025 release |
| Daily | 1.20250301.0 |
First 1 Mar 2025 release |
| Daily | 1.20250301.7 |
Eighth 1 Mar 2025 release |
Progression path:
YYYYβYYYYMMβYYYYMMDD.
- MAJOR = 0 β Alpha, Experiment, PoC (volatile)
- MAJOR β₯ 1 β Stable Release (guarantees apply; breakage = new major)
5. Transitions Examples
Table A - Allowed transitions within the same MAJOR
| From | To | Ξ DATE | Allowed? | Rationale |
|---|---|---|---|---|
1.2025.2 |
1.202503.0 |
+MM | β Yes | Yearly β Monthly - DATE grows (YYYY β YYYYMM) |
1.202507.3 |
1.20250701.0 |
+DD | β Yes | Monthly β Daily - DATE grows (YYYYMM β YYYYMMDD) |
1.20250301.4 |
1.20250301.5 |
= | β Yes | Daily β Daily - PATCH +1, DATE unchanged |
1.202510.0 |
1.202510.1 |
= | β Yes | Monthly β Monthly - PATCH +1 |
1.2025.0 |
1.2025.1 |
= | β Yes | Yearly β Yearly - PATCH +1 |
Table B - Transitions that shrink DATE or require a MAJOR bump
| From | To | Ξ DATE | Allowed? | Correct option |
|---|---|---|---|---|
1.20250301.4 |
1.2026.0 |
-DD/MM | β No | Bump MAJOR β 2.2026.0 |
1.20250301.4 |
2.2026.0 |
reset | β Yes | MAJOR bump resets cadence |
2.20271225.6 |
2.202712.7 |
-DD | β No | Keep daily cadence or bump MAJOR |
Date-Only-Grows: DATE cannot shrink inside the same MAJOR; a MAJOR bump resets the cadence.
Extended Semantics
Pre-release identifiers follow SemVer precedence:
1.202503.0-alpha.1<1.202503.0-beta.1<1.202503.0-rc1<1.202503.0
Build metadata (ignored in precedence):
1.202503.0+linux.amd641.202503.0+sha.42ab1ef
Migration
Because every ScalVer tag is syntactically valid SemVer, most projects can keep their existing tooling unchanged or with only minimal tweaks.
SemVer β ScalVer Example
| Format | New Variant | LengthΒΉ | Ξ vs 1.23.5 |
Conversion |
|---|---|---|---|---|
xMAJOR.YYYY.xPATCH |
1.2025.5 |
8 | +2 | Major & Patch preserved; Year replaces Minor |
xMAJOR.YYYYMM.xPATCH |
1.202504.5 |
10 | +4 | Major & Patch preserved; Year-Month replaces Minor |
xMAJOR.YYYYMMDD.xPATCH |
1.20250421.5 |
12 | +6 | Major & Patch preserved; Y-M-D replaces Minor |
xMAJOR.YYYY.xMINORxPATCH |
1.2025.235 |
10 | +4 | Major preserved; Minor & Patch concatenated |
xMINOR.YYYY.PATCH |
23.2025.0 |
9 | +3 | Minor promoted to leading segment; Major dropped |
xMINOR.YYYY.PATCH |
23.2025.5 |
9 | +3 | Minor promoted to leading segment; Major dropped; Patch preserved |
ΒΉ Log & storage overhead example(assuming (1) one-byte UTF-8 characters and (2) no compression/deduplication): a +6 variant could inflates log lines by 6 MB per million tags and consumes 6 MB more disk per million stored records.
Playbook
Quick path (most projects):
- Choose calendar width β
YYYY,YYYYMM, orYYYYMMDD. - Reset
PATCHto0. - Keep
MAJORunless you also break the API. - Publish
MAJOR.DATE.0.
Guard against legacy MINOR overflows:
maxMinor = max(X in MAJOR.X.PATCH)- Compute today's
DATE(YYYYMMDDorYYYYMMorYYYY). - Compare
DATE > maxMinorβ tagMAJOR.DATE.0.DATE β€ maxMinorβ Increment MAJOR and tagnewMAJOR.DATE.0.
Note Option B (incrementing MAJOR) may be unacceptable in ecosystems where MAJOR is tightly coupled to compatibility promises or installer heuristics. Prefer widening the DATE slot whenever possible; choose a MAJOR bump only when all stakeholders agree it won't disrupt dependency resolution policies.
FAQ
-
Can I use ScalVer with Cargo / Maven / npm / Go / Python? - Yes; all treat
<DATE>as MINOR, so caret (^) and tilde (~) ranges still work unchanged. -
What if we tag
1.202503.0for March 2025 and later jump to1.20250225.0, which looks like the year 202 502 25 A.D.?
Within a MAJOR line, the DATE segment may grow but must never shrink; you can shorten it only after bumping to a new MAJOR version (see 5); nonetheless:
1. Y10K perspective - ScalVer comparisons remain correct with years > 9999; there's no intrinsic cap. For interoperability, the reference grammar sticks to four-digitYYYY. Teams needing post-9999 dating may (a) extend theYYYYfield (i.e,YYYYYYYY), or (b) bump MAJOR and restart atYYYY = 0000.
2. ISO-8601 perspective - By default we enforce four-digit years for maximum tooling compatibility. Under this rule20250225unambiguously parses to 2025-02-25. A later yearly tag (e.g. the future β20250225β year example) can't shrinkDATEwithin MAJOR 1 -
Is ScalVer an extension of SemVer? - No. ScalVer tags are a syntactic subset of SemVer, yet they intentionally diverge semantically by repurposing the MINOR field as a calendar date.
Acknowledgements
ScalVer's versioning aligns closely with the scheme used by plantuml/plantuml, plantuml.com. We thank Arnaud Roques for kindly permitting us to cite PlantUML as a practical precedent.
Links
- Semantic Versioning 2.0
- Calendar Versioning
- Semantic Import Versioning
- https://github.com/plantuml/plantuml
Zero Trackers. Want to leave a footprint? Open a PR and bump the counter.