
Parse and compare semantic-style version strings with optional prefixes, pre-release and build metadata; treats empty subparts as zero, ignores prefixes/build metadata for ordering, supports numeric/alphanumeric ordering.
A version in this project consists of four parts:
v, release-).major.minor.patch (e.g., 1.2.3).-alpha.1).+build.20251121).1.2.3, alpha.1, build.20251121).1..1) are treated as "0". This means 1..1 is parsed as 1.0.1, and similarly, missing pre-release or build metadata subparts are also treated as "0" when accessed by index.1..1 → major=1, minor=0, patch=1
1.2.3-alpha..1 → preRelease=["alpha", "0", "1"]
part(4) for 1.2.3) returns "0".1 in 1.2.3).alpha, rc1, 20251121).| Part | Example | Notes |
|---|---|---|
| Prefix | v, release- | Optional, not dot-separated |
| Version Part | 1.2.3 | Major must be a number |
| PreRelease Part | alpha.1 | Optional, alphanumeric or numeric |
| Build Metadata | build.20251121 | Optional, alphanumeric or numeric |
import nl.w8mr.version.Version
val v1 = Version("1.2.3")
val v2 = Version("v2.0.0-alpha.1+build.20251121")
val v3 = Version("release-2.5.0-rc.2")You can easily create a Version object from a string using the extension function String.toVersion():
val v = "1.2.3-alpha.1+build.20251121".toVersion()
println(v.major) // "1"
println(v.preRelease) // ["alpha", "1"]This is equivalent to calling Version("1.2.3-alpha.1+build.20251121") directly, but provides a more idiomatic way to convert strings to version objects in Kotlin.
println(v1.major) // "1"
println(v2.prefix) // "v"
println(v2.preRelease) // ["alpha", "1"]
println(v2.buildMetadata) // ["build", "20251121"]
// Empty parts are treated as "0"
val v = Version("1..1")
println(v.major) // "1"
println(v.minor) // "0"
println(v.patch) // "1"Versions can be compared to determine which is newer, older, or if they are equal. The comparison follows these rules:
1.2.3 > 1.2.2, 1.2.10 > 1.2.3, 1.2.a > 1.2.9
1.2.3 > 1.2.3-alpha). If both have pre-release parts, compare each dot-separated subpart in order, using numeric or lexicographic comparison as above.
1.2.3-alpha.2 > 1.2.3-alpha.1, 1.2.3-beta > 1.2.3-alpha
1.2.3 > 1.2.3-alpha.1
1.2.3-alpha.2 > 1.2.3-alpha.1
1.2.10 > 1.2.3
v1.2.3 == 1.2.3 (prefix ignored)1.2.3+build.1 == 1.2.3+build.2 (build metadata ignored)val v1 = Version("1.2.3")
val v2 = Version("1.2.3-alpha.1")
val v3 = Version("1.2.10")
println(v1 > v2) // true
println(v3 > v1) // true
println(v1 == Version("v1.2.3")) // true (prefix ignored)
println(Version("1.2.3+build.1") == Version("1.2.3+build.2")) // true (build metadata ignored)val versions = listOf(
Version("1.2.3"),
Version("1.2.3-alpha.1"),
Version("1.2.10"),
Version("v1.2.3"),
Version("1.2.3+build.1")
)
val sorted = versions.sorted()
sorted.forEach { println(it) }A version in this project consists of four parts:
v, release-).major.minor.patch (e.g., 1.2.3).-alpha.1).+build.20251121).1.2.3, alpha.1, build.20251121).1..1) are treated as "0". This means 1..1 is parsed as 1.0.1, and similarly, missing pre-release or build metadata subparts are also treated as "0" when accessed by index.1..1 → major=1, minor=0, patch=1
1.2.3-alpha..1 → preRelease=["alpha", "0", "1"]
part(4) for 1.2.3) returns "0".1 in 1.2.3).alpha, rc1, 20251121).| Part | Example | Notes |
|---|---|---|
| Prefix | v, release- | Optional, not dot-separated |
| Version Part | 1.2.3 | Major must be a number |
| PreRelease Part | alpha.1 | Optional, alphanumeric or numeric |
| Build Metadata | build.20251121 | Optional, alphanumeric or numeric |
import nl.w8mr.version.Version
val v1 = Version("1.2.3")
val v2 = Version("v2.0.0-alpha.1+build.20251121")
val v3 = Version("release-2.5.0-rc.2")You can easily create a Version object from a string using the extension function String.toVersion():
val v = "1.2.3-alpha.1+build.20251121".toVersion()
println(v.major) // "1"
println(v.preRelease) // ["alpha", "1"]This is equivalent to calling Version("1.2.3-alpha.1+build.20251121") directly, but provides a more idiomatic way to convert strings to version objects in Kotlin.
println(v1.major) // "1"
println(v2.prefix) // "v"
println(v2.preRelease) // ["alpha", "1"]
println(v2.buildMetadata) // ["build", "20251121"]
// Empty parts are treated as "0"
val v = Version("1..1")
println(v.major) // "1"
println(v.minor) // "0"
println(v.patch) // "1"Versions can be compared to determine which is newer, older, or if they are equal. The comparison follows these rules:
1.2.3 > 1.2.2, 1.2.10 > 1.2.3, 1.2.a > 1.2.9
1.2.3 > 1.2.3-alpha). If both have pre-release parts, compare each dot-separated subpart in order, using numeric or lexicographic comparison as above.
1.2.3-alpha.2 > 1.2.3-alpha.1, 1.2.3-beta > 1.2.3-alpha
1.2.3 > 1.2.3-alpha.1
1.2.3-alpha.2 > 1.2.3-alpha.1
1.2.10 > 1.2.3
v1.2.3 == 1.2.3 (prefix ignored)1.2.3+build.1 == 1.2.3+build.2 (build metadata ignored)val v1 = Version("1.2.3")
val v2 = Version("1.2.3-alpha.1")
val v3 = Version("1.2.10")
println(v1 > v2) // true
println(v3 > v1) // true
println(v1 == Version("v1.2.3")) // true (prefix ignored)
println(Version("1.2.3+build.1") == Version("1.2.3+build.2")) // true (build metadata ignored)val versions = listOf(
Version("1.2.3"),
Version("1.2.3-alpha.1"),
Version("1.2.10"),
Version("v1.2.3"),
Version("1.2.3+build.1")
)
val sorted = versions.sorted()
sorted.forEach { println(it) }