From ca05cae1575521ebd152dd54fa2f9580c1ea9746 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Mon, 4 May 2026 17:02:22 +0100 Subject: [PATCH 01/12] Bump version -> `2.0.0-SNAPSHOT.238` --- version.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.gradle.kts b/version.gradle.kts index 388e257dc..5853fe8eb 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -27,4 +27,4 @@ /** * The version of this library for publishing. */ -val versionToPublish by extra("2.0.0-SNAPSHOT.237") +val versionToPublish by extra("2.0.0-SNAPSHOT.238") From 5f828374994d31d964b4fb4d19dad34f758a7683 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Mon, 4 May 2026 17:05:51 +0100 Subject: [PATCH 02/12] Make `spine` package explicit in field references Also: * Remove unnecessary package prefixes. --- .../proto/spine/tools/time/validation/events.proto | 10 +++++----- .../main/proto/spine/tools/time/validation/views.proto | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/validation/src/main/proto/spine/tools/time/validation/events.proto b/validation/src/main/proto/spine/tools/time/validation/events.proto index fda7ff16c..18de2d054 100644 --- a/validation/src/main/proto/spine/tools/time/validation/events.proto +++ b/validation/src/main/proto/spine/tools/time/validation/events.proto @@ -39,14 +39,14 @@ import "spine/compiler/ast.proto"; import "spine/time_options.proto"; import "spine/tools/time/validation/time_field_type.proto"; -// The event emitted whenever a field with `(when)` option is discovered -// and has passed the necessary checks to confirm the option is applied correctly. +// The event emitted whenever a field with `(when)` option is discovered and +// has passed the necessary checks to confirm the option is applied correctly. message WhenFieldDiscovered { - compiler.FieldRef id = 1; + spine.compiler.FieldRef id = 1; // The field in which the option was discovered. - compiler.Field subject = 2; + spine.compiler.Field subject = 2; // The error message template. string error_message = 3; @@ -55,5 +55,5 @@ message WhenFieldDiscovered { Time bound = 4; // The type of the field. - spine.tools.time.validation.TimeFieldType type = 5; + TimeFieldType type = 5; } diff --git a/validation/src/main/proto/spine/tools/time/validation/views.proto b/validation/src/main/proto/spine/tools/time/validation/views.proto index e18d6e17f..0f1966c17 100644 --- a/validation/src/main/proto/spine/tools/time/validation/views.proto +++ b/validation/src/main/proto/spine/tools/time/validation/views.proto @@ -43,10 +43,10 @@ import "spine/tools/time/validation/time_field_type.proto"; message WhenField { option (entity).kind = PROJECTION; - compiler.FieldRef id = 1; + spine.compiler.FieldRef id = 1; // The field in which the option was discovered. - compiler.Field subject = 2; + spine.compiler.Field subject = 2; // The error message template. string error_message = 3; @@ -55,5 +55,5 @@ message WhenField { Time bound = 4; // The type of the field. - spine.tools.time.validation.TimeFieldType type = 5; + TimeFieldType type = 5; } From 7edc7e436c39aa81f6e86fe6a7d0738b2b552df3 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Mon, 4 May 2026 17:05:59 +0100 Subject: [PATCH 03/12] Update dependency reports --- dependencies.md | 30 +++++++++++++++--------------- pom.xml | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/dependencies.md b/dependencies.md index df15203e7..cc4fd553b 100644 --- a/dependencies.md +++ b/dependencies.md @@ -1,6 +1,6 @@ -# Dependencies of `io.spine.tools:time-gradle-plugin:2.0.0-SNAPSHOT.237` +# Dependencies of `io.spine.tools:time-gradle-plugin:2.0.0-SNAPSHOT.238` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -1059,14 +1059,14 @@ The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Fri May 01 17:48:31 WEST 2026** using +This report was generated on **Mon May 04 17:04:48 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:time-testlib:2.0.0-SNAPSHOT.237` +# Dependencies of `io.spine.tools:time-testlib:2.0.0-SNAPSHOT.238` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -1869,14 +1869,14 @@ This report was generated on **Fri May 01 17:48:31 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Fri May 01 17:48:31 WEST 2026** using +This report was generated on **Mon May 04 17:04:48 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine:spine-time:2.0.0-SNAPSHOT.237` +# Dependencies of `io.spine:spine-time:2.0.0-SNAPSHOT.238` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -2833,14 +2833,14 @@ This report was generated on **Fri May 01 17:48:31 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Fri May 01 17:48:31 WEST 2026** using +This report was generated on **Mon May 04 17:04:48 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine:spine-time-java:2.0.0-SNAPSHOT.237` +# Dependencies of `io.spine:spine-time-java:2.0.0-SNAPSHOT.238` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -3643,14 +3643,14 @@ This report was generated on **Fri May 01 17:48:31 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Fri May 01 17:48:31 WEST 2026** using +This report was generated on **Mon May 04 17:04:48 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine:spine-time-kotlin:2.0.0-SNAPSHOT.237` +# Dependencies of `io.spine:spine-time-kotlin:2.0.0-SNAPSHOT.238` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -4461,14 +4461,14 @@ This report was generated on **Fri May 01 17:48:31 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Fri May 01 17:48:31 WEST 2026** using +This report was generated on **Mon May 04 17:04:48 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:time-validation:2.0.0-SNAPSHOT.237` +# Dependencies of `io.spine.tools:time-validation:2.0.0-SNAPSHOT.238` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -5590,14 +5590,14 @@ This report was generated on **Fri May 01 17:48:31 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Fri May 01 17:48:31 WEST 2026** using +This report was generated on **Mon May 04 17:04:48 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine:spine-validation-tests:2.0.0-SNAPSHOT.237` +# Dependencies of `io.spine:spine-validation-tests:2.0.0-SNAPSHOT.238` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -6683,6 +6683,6 @@ This report was generated on **Fri May 01 17:48:31 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Fri May 01 17:48:31 WEST 2026** using +This report was generated on **Mon May 04 17:04:48 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under -[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). \ No newline at end of file +[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). diff --git a/pom.xml b/pom.xml index 8ba7a58fe..c9b3c87ee 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ all modules and does not describe the project structure per-subproject. --> io.spine spine-time -2.0.0-SNAPSHOT.237 +2.0.0-SNAPSHOT.238 2015 From 641764181f5035f2195bd6781e974f15d9ab1cda Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Mon, 4 May 2026 17:06:24 +0100 Subject: [PATCH 04/12] Update `config` --- .agents/skills/writer/SKILL.md | 29 +++++++++++++++++++++++++++-- config | 2 +- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/.agents/skills/writer/SKILL.md b/.agents/skills/writer/SKILL.md index 5c720265b..30cb51e38 100644 --- a/.agents/skills/writer/SKILL.md +++ b/.agents/skills/writer/SKILL.md @@ -3,7 +3,7 @@ name: writer description: > Write, edit, and restructure user-facing and developer-facing documentation. Use when asked to create/update docs such as `README.md`, `docs/**`, and - other Markdown documentation; + other Markdown documentation, including keeping docs navigation data in sync; when drafting tutorials, guides, troubleshooting pages, or migration notes; and when improving inline API documentation (KDoc) and examples. --- @@ -24,10 +24,36 @@ description: > - `docs/`: longer-form docs (follow existing conventions in that tree). - Source KDoc: API usage, examples, and semantics that belong with the code. +## Keep docs navigation in sync + +- When adding, removing, moving, or renaming a page under + `docs/content/docs/
/`, keep the current version's matching + `sidenav.yml` in sync. +- Use `docs/data/versions.yml` to identify the current documentation version for + that section. The current version is the entry with `is_main: true`; its + `version_id` maps to `docs/data/docs/
//sidenav.yml`. +- Do not update historical version entries or their navigation files unless the + user explicitly asks to edit that historical version. +- Map page files to `file_path` values relative to the current version's + `content_path`, without `.md`; `_index.md` maps to its directory path, such as + `01-getting-started/_index.md` -> `01-getting-started`. +- Keep each `page` label aligned with the page frontmatter `title` unless the + existing navigation intentionally uses a shorter reader-facing label. +- Preserve the existing ordering, nesting, keys, comments, and YAML quoting + style. Remove nav entries for deleted pages and update `file_path` values for + moved pages. +- If a docs content change should not appear in navigation, say so explicitly in + the final response. + ## Follow local documentation conventions - Follow `.agents/documentation-guidelines.md` and `.agents/documentation-tasks.md`. - Use fenced code blocks for commands and examples; format file/dir names as code. +- In Markdown files, prefer footnote-style reference links for external `https://` + targets instead of inline links. Write readable body text like + `[label][short-id]`, then place the URL definition near the end of the file, + such as `[short-id]: https://example.com/long/path`. Keep reference IDs short + and descriptive. Inline links are still fine for local relative paths. - Avoid widows, runts, orphans, and rivers by reflowing paragraphs when needed. ## Make docs actionable @@ -48,4 +74,3 @@ description: > - For code changes, follow `.agents/running-builds.md`. - For documentation-only changes in Kotlin/Java sources, prefer `./gradlew dokka`. - diff --git a/config b/config index f24236f0a..85bbe5475 160000 --- a/config +++ b/config @@ -1 +1 @@ -Subproject commit f24236f0a897e9d6a101e60d1dd936317c7a3c06 +Subproject commit 85bbe547558ee9fd076d0791b13c836b927ecfb8 From d6d72cd8b2b9acf3853d25e91e3573792a63aded Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Mon, 4 May 2026 17:12:39 +0100 Subject: [PATCH 05/12] Update dependency reports --- dependencies.md | 14 +++++++------- pom.xml | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dependencies.md b/dependencies.md index cc4fd553b..20e235530 100644 --- a/dependencies.md +++ b/dependencies.md @@ -1059,7 +1059,7 @@ The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 04 17:04:48 WEST 2026** using +This report was generated on **Mon May 04 17:09:31 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). @@ -1869,7 +1869,7 @@ This report was generated on **Mon May 04 17:04:48 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 04 17:04:48 WEST 2026** using +This report was generated on **Mon May 04 17:09:31 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). @@ -2833,7 +2833,7 @@ This report was generated on **Mon May 04 17:04:48 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 04 17:04:48 WEST 2026** using +This report was generated on **Mon May 04 17:09:31 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). @@ -3643,7 +3643,7 @@ This report was generated on **Mon May 04 17:04:48 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 04 17:04:48 WEST 2026** using +This report was generated on **Mon May 04 17:09:31 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). @@ -4461,7 +4461,7 @@ This report was generated on **Mon May 04 17:04:48 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 04 17:04:48 WEST 2026** using +This report was generated on **Mon May 04 17:09:31 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). @@ -5590,7 +5590,7 @@ This report was generated on **Mon May 04 17:04:48 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 04 17:04:48 WEST 2026** using +This report was generated on **Mon May 04 17:09:31 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). @@ -6683,6 +6683,6 @@ This report was generated on **Mon May 04 17:04:48 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 04 17:04:48 WEST 2026** using +This report was generated on **Mon May 04 17:09:31 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). diff --git a/pom.xml b/pom.xml index c9b3c87ee..d2aec18db 100644 --- a/pom.xml +++ b/pom.xml @@ -56,7 +56,7 @@ all modules and does not describe the project structure per-subproject. io.spine spine-time - 2.0.0-SNAPSHOT.236 + 2.0.0-SNAPSHOT.237 compile From f23438c3cded32035d5296a6e798ff8b4fc8a737 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Mon, 4 May 2026 17:12:55 +0100 Subject: [PATCH 06/12] Bump Time -> `2.0.0-SNAPSHOT.237` --- buildSrc/src/main/kotlin/io/spine/dependency/local/Time.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/Time.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/Time.kt index 05eb7bfaf..7be4e8473 100644 --- a/buildSrc/src/main/kotlin/io/spine/dependency/local/Time.kt +++ b/buildSrc/src/main/kotlin/io/spine/dependency/local/Time.kt @@ -40,7 +40,7 @@ import io.spine.dependency.Dependency ) object Time : Dependency() { override val group = Spine.group - override val version = "2.0.0-SNAPSHOT.236" + override val version = "2.0.0-SNAPSHOT.237" private const val infix = "spine-time" fun lib(version: String): String = "$group:$infix:$version" From a6d9c3a2fb7a2f5d5487fd1d53d6d0cfd23f0dc9 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Mon, 4 May 2026 17:17:37 +0100 Subject: [PATCH 07/12] Describe compatibility with `kotlinx-datetime` --- README.md | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 423706772..eb98a8878 100644 --- a/README.md +++ b/README.md @@ -15,14 +15,13 @@ The types provided by this library follow the conventions offered by [Java Time] ## Supported programming languages -The library currently supports Java, Kotlin (Protobuf DSL), and JavaScript. +The library currently supports Java and Kotlin (Protobuf DSL and +compatibility with [`kotlinx-datetime`][kotlinx-datetime]). -For JavaScript code, please see the [`time-js`](./time-js) module. +The versions `1.*` are built using Java 8. -The versions `1.x` and early `2.x` snapshots are built using Java 8. - -Starting `2.0.0-SNAPSHOT.76`, all modules are built with Java 11. Therefore, consumer projects -should aim for Java 11+ to use them. +The versions `2.*` are built with Java 17. +Therefore, consumer projects should aim for Java 17+ to use them. ## Using Spine Time in a Gradle project @@ -30,20 +29,15 @@ To add a dependency to a Gradle project, please use the following: ```kotlin dependencies { - implementation("io.spine:spine-time:$spineVersion") + implementation("io.spine:spine-time:$version") } ``` In addition to the generated types and basic factory and calculation routines, the library -provides converters between its types and Java Time. It is expected that an application code would -perform the date/time calculations using Java Time. - -## Integration with `kotlinx-datetime` - -Compatibility with [`kotlinx-datetime`][kotlinx-datetime] [planned][issue-113] for v2.0. +provides converters between its types and Java Time and [`kotlinx-datetime`][kotlinx-datetime]. +It is expected that an application code would perform the date/time calculations using Java Time or +[`kotlinx-datetime`][kotlinx-datetime]. -[travis]: https://travis-ci.com/SpineEventEngine/time -[travis-badge]: https://travis-ci.com/SpineEventEngine/time.svg?branch=master [codecov]: https://codecov.io/gh/SpineEventEngine/time [codecov-badge]: https://codecov.io/gh/SpineEventEngine/time/branch/master/graph/badge.svg [license-badge]: https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat @@ -51,4 +45,3 @@ Compatibility with [`kotlinx-datetime`][kotlinx-datetime] [planned][issue-113] f [java-time]: http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html [kotlinx-datetime]: https://github.com/Kotlin/kotlinx-datetime -[issue-113]: https://github.com/SpineEventEngine/time/issues/113 From 8a357f440100d7061efb5b6df5d2a42781c7631a Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Mon, 4 May 2026 17:30:28 +0100 Subject: [PATCH 08/12] Remove unnecessary nesting of tests --- .../java/TimestampRepeatedWhenSpec.kt | 144 +++++++++--------- 1 file changed, 70 insertions(+), 74 deletions(-) diff --git a/tests/src/test/kotlin/io/spine/tools/time/validation/java/TimestampRepeatedWhenSpec.kt b/tests/src/test/kotlin/io/spine/tools/time/validation/java/TimestampRepeatedWhenSpec.kt index 9954a946e..5033fcee6 100644 --- a/tests/src/test/kotlin/io/spine/tools/time/validation/java/TimestampRepeatedWhenSpec.kt +++ b/tests/src/test/kotlin/io/spine/tools/time/validation/java/TimestampRepeatedWhenSpec.kt @@ -39,113 +39,109 @@ import org.junit.jupiter.api.Test internal class TimestampRepeatedWhenSpec { @Nested inner class - `when given several timestamps` { + `denoting only the past` { - @Nested inner class - `denoting only the past` { + private val severalPastTimes = listOf(pastTime(), pastTime(), pastTime()) - private val severalPastTimes = listOf(pastTime(), pastTime(), pastTime()) - - @Test - fun `throw, if restricted to be in future`() = assertValidationFails { - futureProtoTimestamps { - value.addAll(severalPastTimes) - } + @Test + fun `throw, if restricted to be in future`() = assertValidationFails { + futureProtoTimestamps { + value.addAll(severalPastTimes) } + } - @Test - fun `pass, if restricted to be in past`() = assertValidationPasses { - pastProtoTimestamps { - value.addAll(severalPastTimes) - } + @Test + fun `pass, if restricted to be in past`() = assertValidationPasses { + pastProtoTimestamps { + value.addAll(severalPastTimes) } + } - @Test - fun `pass, if not restricted at all`() = assertValidationPasses { - anyProtoTimestamps { - value.addAll(severalPastTimes) - } + @Test + fun `pass, if not restricted at all`() = assertValidationPasses { + anyProtoTimestamps { + value.addAll(severalPastTimes) } } + } - @Nested inner class - `denoting only the future` { + @Nested inner class + `denoting only the future` { - private val severalFutureTimes = listOf(futureTime(), futureTime(), futureTime()) + private val severalFutureTimes = listOf(futureTime(), futureTime(), futureTime()) - @Test - fun `throw, if restricted to be in past`() = assertValidationFails { - pastProtoTimestamps { - value.addAll(severalFutureTimes) - } + @Test + fun `throw, if restricted to be in past`() = assertValidationFails { + pastProtoTimestamps { + value.addAll(severalFutureTimes) } + } - @Test - fun `pass, if restricted to be in future`() = assertValidationPasses { - futureProtoTimestamps { - value.addAll(severalFutureTimes) - } + @Test + fun `pass, if restricted to be in future`() = assertValidationPasses { + futureProtoTimestamps { + value.addAll(severalFutureTimes) } + } - @Test - fun `pass, if not restricted at all`() = assertValidationPasses { - anyProtoTimestamps { - value.addAll(severalFutureTimes) - } + @Test + fun `pass, if not restricted at all`() = assertValidationPasses { + anyProtoTimestamps { + value.addAll(severalFutureTimes) } } + } - @Nested inner class - `with a single past stamp within the future stamps` { + @Nested inner class + `with a single past stamp within the future stamps` { - private val severalFutureAndPast = listOf(futureTime(), pastTime(), futureTime()) + private val severalFutureAndPast = listOf(futureTime(), pastTime(), futureTime()) - @Test - fun `throw, if restricted to be in future`() = assertValidationFails { - futureProtoTimestamps { - value.addAll(severalFutureAndPast) - } + @Test + fun `throw, if restricted to be in future`() = assertValidationFails { + futureProtoTimestamps { + value.addAll(severalFutureAndPast) } + } - @Test - fun `throw, if restricted to be in past`() = assertValidationFails { - pastProtoTimestamps { - value.addAll(severalFutureAndPast) - } + @Test + fun `throw, if restricted to be in past`() = assertValidationFails { + pastProtoTimestamps { + value.addAll(severalFutureAndPast) } + } - @Test - fun `pass, if not restricted at all`() = assertValidationPasses { - anyProtoTimestamps { - value.addAll(severalFutureAndPast) - } + @Test + fun `pass, if not restricted at all`() = assertValidationPasses { + anyProtoTimestamps { + value.addAll(severalFutureAndPast) } } + } - @Nested inner class - `with a single future stamp within the past stamps` { + @Nested inner class + `with a single future stamp within the past stamps` { - private val severalPastAndFuture = listOf(pastTime(), futureTime(), pastTime()) + private val severalPastAndFuture = listOf(pastTime(), futureTime(), pastTime()) - @Test - fun `throw, if restricted to be in future`() = assertValidationFails { - futureProtoTimestamps { - value.addAll(severalPastAndFuture) - } + @Test + fun `throw, if restricted to be in future`() = assertValidationFails { + futureProtoTimestamps { + value.addAll(severalPastAndFuture) } + } - @Test - fun `throw, if restricted to be in past`() = assertValidationFails { - pastProtoTimestamps { - value.addAll(severalPastAndFuture) - } + @Test + fun `throw, if restricted to be in past`() = assertValidationFails { + pastProtoTimestamps { + value.addAll(severalPastAndFuture) } + } - @Test - fun `pass, if not restricted at all`() = assertValidationPasses { - anyProtoTimestamps { - value.addAll(severalPastAndFuture) - } + @Test + fun `pass, if not restricted at all`() = assertValidationPasses { + anyProtoTimestamps { + value.addAll(severalPastAndFuture) } } } From d91b637394ccc7fd4b805190fb4828a8ed4ea500 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Mon, 4 May 2026 17:32:32 +0100 Subject: [PATCH 09/12] Describe using the Time Gradle plugin --- README.md | 116 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 102 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index eb98a8878..e994a0503 100644 --- a/README.md +++ b/README.md @@ -8,40 +8,128 @@ [ubuntu-build-badge]: https://github.com/SpineEventEngine/time/actions/workflows/build-on-ubuntu.yml/badge.svg -In addition to `Timestamp` and `Duration` natively available from Protobuf, the Spine Time library -provides a set of data types for describing date and time in a business model. +In addition to `Timestamp` and `Duration` natively available from Protobuf, the Spine Time library +provides a set of data types for describing date and time in a business model. The types provided by this library follow the conventions offered by [Java Time][java-time]. ## Supported programming languages The library currently supports Java and Kotlin (Protobuf DSL and -compatibility with [`kotlinx-datetime`][kotlinx-datetime]). +compatibility with [`kotlinx-datetime`][kotlinx-datetime]). -The versions `1.*` are built using Java 8. +The versions `1.*` are built using Java 8. -The versions `2.*` are built with Java 17. +The versions `2.*` are built with Java 17. Therefore, consumer projects should aim for Java 17+ to use them. - -## Using Spine Time in a Gradle project -To add a dependency to a Gradle project, please use the following: +## Using the Time Gradle plugin + +The recommended way to add Spine Time to a project is via the `io.spine.time` Gradle plugin. +Apply it after a JVM language plugin (`java`, `java-library`, or `kotlin("jvm")`): + +```kotlin +plugins { + id("io.spine.time") +} +``` + +The plugin automatically adds `io.spine:spine-time` as an `implementation` dependency. + +### Optional modules + +Use the `time` extension block to opt in to additional modules: + +```kotlin +spine { + time { + useJavaExtensions.set(true) // adds `spine-time-java` (Java Time converters) + useKotlinExtensions.set(true) // adds `spine-time-kotlin` (kotlinx-datetime converters) + useTestLib.set(true) // adds `time-testlib` as testImplementation + } +} +``` + +All three flags default to `false`. + +### Manual dependency + +If you prefer to manage the dependency directly rather than through the plugin: ```kotlin dependencies { - implementation("io.spine:spine-time:$version") + implementation("io.spine:spine-time:$version") +} +``` + +## Validating time fields with `(when)` + +The `(when)` Protobuf field option constrains a time-valued field so that it must hold +a value either in the past or in the future. + +It applies to: + +- `google.protobuf.Timestamp` +- Any type from the `spine.time` package (e.g. `LocalDateTime`, `ZonedDateTime`) +- Repeated and map fields of the above types + +### Enabling validation + +The `(when)` option requires the [Spine Validation][validation] Gradle plugin. The `io.spine.time` +plugin automatically registers the `time-validation` module on the compiler classpath when +`io.spine.validation` is also applied: + +```kotlin +plugins { + id("io.spine.validation") + id("io.spine.time") } ``` -In addition to the generated types and basic factory and calculation routines, the library -provides converters between its types and Java Time and [`kotlinx-datetime`][kotlinx-datetime]. -It is expected that an application code would perform the date/time calculations using Java Time or -[`kotlinx-datetime`][kotlinx-datetime]. +### Usage + +```protobuf +import "spine/time_options.proto"; + +message ScheduleMeeting { + spine.time.ZonedDateTime start = 1 [(when).in = FUTURE]; + spine.time.ZonedDateTime end = 2 [(when).in = FUTURE]; +} + +message AuditRecord { + google.protobuf.Timestamp occurred_at = 1 [(when).in = PAST]; +} +``` + +The `Time` enum accepts two values: + +| Value | Meaning | +|----------|--------------------------------| +| `PAST` | The field value must be in the past | +| `FUTURE` | The field value must be in the future | + +### Custom error messages + +Supply a custom message via `error_msg`. The following placeholders are available: + +- `${field.path}` — the field path +- `${field.value}` — the field value +- `${field.type}` — the fully qualified name of the field type +- `${parent.type}` — the fully qualified name of the validated message +- `${when.in}` — the restriction, either `"past"` or `"future"` + +```protobuf +google.protobuf.Timestamp scheduled_at = 1 [(when) = { + in: FUTURE, + error_msg: "The meeting must be scheduled in the future, but got `${field.value}`." +}]; +``` [codecov]: https://codecov.io/gh/SpineEventEngine/time [codecov-badge]: https://codecov.io/gh/SpineEventEngine/time/branch/master/graph/badge.svg [license-badge]: https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat [license]: http://www.apache.org/licenses/LICENSE-2.0 -[java-time]: http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html +[java-time]: http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html [kotlinx-datetime]: https://github.com/Kotlin/kotlinx-datetime +[validation]: https://github.com/SpineEventEngine/validation From 169239cc5f60b4c84b54c921d1d4974536e4ad00 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Mon, 4 May 2026 17:40:25 +0100 Subject: [PATCH 10/12] Clarify using Time as a standalone library --- README.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e994a0503..10d64aed9 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,18 @@ The versions `1.*` are built using Java 8. The versions `2.*` are built with Java 17. Therefore, consumer projects should aim for Java 17+ to use them. +## Integration with Spine CoreJvm + +Projects based on the [Spine CoreJvm][core-jvm] library do not need to configure Time manually. +The [CoreJvm Compiler][core-jvm-compiler] automatically adds and configures Spine Time, including +the `(when)` validation support. + +The sections below apply only when using Spine Time as a **standalone** library, without CoreJvm. + ## Using the Time Gradle plugin -The recommended way to add Spine Time to a project is via the `io.spine.time` Gradle plugin. -Apply it after a JVM language plugin (`java`, `java-library`, or `kotlin("jvm")`): +The recommended way to add Spine Time to a standalone project is via the `io.spine.time` Gradle +plugin. Apply it after a JVM language plugin (`java`, `java-library`, or `kotlin("jvm")`): ```kotlin plugins { @@ -44,8 +52,8 @@ Use the `time` extension block to opt in to additional modules: spine { time { useJavaExtensions.set(true) // adds `spine-time-java` (Java Time converters) - useKotlinExtensions.set(true) // adds `spine-time-kotlin` (kotlinx-datetime converters) - useTestLib.set(true) // adds `time-testlib` as testImplementation + useKotlinExtensions.set(true) // adds `spine-time-kotlin` (`kotlinx-datetime` converters) + useTestLib.set(true) // adds `time-testlib` as `testImplementation` } } ``` @@ -130,6 +138,8 @@ google.protobuf.Timestamp scheduled_at = 1 [(when) = { [license-badge]: https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat [license]: http://www.apache.org/licenses/LICENSE-2.0 +[core-jvm]: https://github.com/SpineEventEngine/core-jvm/ +[core-jvm-compiler]: https://github.com/SpineEventEngine/core-jvm-compiler/ [java-time]: http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html [kotlinx-datetime]: https://github.com/Kotlin/kotlinx-datetime [validation]: https://github.com/SpineEventEngine/validation From fa55ae7190aa79f40d2c9952f6afbd1ab7bee186 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Mon, 4 May 2026 17:41:28 +0100 Subject: [PATCH 11/12] Clarify what `(when)` is --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 10d64aed9..152a9d560 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Therefore, consumer projects should aim for Java 17+ to use them. Projects based on the [Spine CoreJvm][core-jvm] library do not need to configure Time manually. The [CoreJvm Compiler][core-jvm-compiler] automatically adds and configures Spine Time, including -the `(when)` validation support. +the `(when)` option validation support. The sections below apply only when using Spine Time as a **standalone** library, without CoreJvm. From f551d891bd0896530983099e6b2e86f5b493d252 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Mon, 4 May 2026 17:46:23 +0100 Subject: [PATCH 12/12] Update build time --- dependencies.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dependencies.md b/dependencies.md index 20e235530..474c7fad7 100644 --- a/dependencies.md +++ b/dependencies.md @@ -1059,7 +1059,7 @@ The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 04 17:09:31 WEST 2026** using +This report was generated on **Mon May 04 17:42:46 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). @@ -1869,7 +1869,7 @@ This report was generated on **Mon May 04 17:09:31 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 04 17:09:31 WEST 2026** using +This report was generated on **Mon May 04 17:42:46 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). @@ -2833,7 +2833,7 @@ This report was generated on **Mon May 04 17:09:31 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 04 17:09:31 WEST 2026** using +This report was generated on **Mon May 04 17:42:46 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). @@ -3643,7 +3643,7 @@ This report was generated on **Mon May 04 17:09:31 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 04 17:09:31 WEST 2026** using +This report was generated on **Mon May 04 17:42:46 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). @@ -4461,7 +4461,7 @@ This report was generated on **Mon May 04 17:09:31 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 04 17:09:31 WEST 2026** using +This report was generated on **Mon May 04 17:42:46 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). @@ -5590,7 +5590,7 @@ This report was generated on **Mon May 04 17:09:31 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 04 17:09:31 WEST 2026** using +This report was generated on **Mon May 04 17:42:47 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). @@ -6683,6 +6683,6 @@ This report was generated on **Mon May 04 17:09:31 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 04 17:09:31 WEST 2026** using +This report was generated on **Mon May 04 17:42:47 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).