Compare commits

...

No commits in common. "v0.1.0" and "master" have entirely different histories.

19 changed files with 489 additions and 183 deletions

1
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1 @@
* @jotoho

8
.gitignore vendored
View File

@ -31,10 +31,12 @@ hs_err_pid*
build
# Ignore gradle wrapper
/gradle
/gradlew
/gradlew.bat
gradlew
gradlew.bat
# Ignore manual compilation results
/de/jotoho/
/META-INF
/.idea/*
!/.idea/codeStyles/
*.zst

View File

@ -0,0 +1,84 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="LINE_SEPARATOR" value="&#10;" />
<option name="RIGHT_MARGIN" value="100" />
<option name="WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN" value="true" />
<option name="ENABLE_SECOND_REFORMAT" value="true" />
<option name="SOFT_MARGINS" value="80" />
<JavaCodeStyleSettings>
<option name="ANNOTATION_PARAMETER_WRAP" value="5" />
<option name="ALIGN_MULTILINE_ANNOTATION_PARAMETERS" value="true" />
<option name="ALIGN_MULTILINE_TEXT_BLOCKS" value="true" />
<option name="JD_ADD_BLANK_AFTER_PARM_COMMENTS" value="true" />
<option name="JD_ADD_BLANK_AFTER_RETURN" value="true" />
<option name="JD_P_AT_EMPTY_LINES" value="false" />
<option name="JD_KEEP_INVALID_TAGS" value="false" />
<option name="JD_KEEP_EMPTY_LINES" value="false" />
<option name="JD_DO_NOT_WRAP_ONE_LINE_COMMENTS" value="true" />
<option name="JD_PARAM_DESCRIPTION_ON_NEW_LINE" value="true" />
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="CONTINUATION_INDENT_IN_PARAMETER_LISTS" value="false" />
<option name="CONTINUATION_INDENT_IN_ARGUMENT_LISTS" value="false" />
<option name="CONTINUATION_INDENT_FOR_CHAINED_CALLS" value="false" />
<option name="CONTINUATION_INDENT_IN_SUPERTYPE_LISTS" value="false" />
<option name="WRAP_EXPRESSION_BODY_FUNCTIONS" value="1" />
</JetCodeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="KEEP_BLANK_LINES_BETWEEN_PACKAGE_DECLARATION_AND_HEADER" value="0" />
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
<option name="ALIGN_MULTILINE_CHAINED_METHODS" value="true" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_ASSIGNMENT" value="true" />
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_THROWS_LIST" value="true" />
<option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
<option name="ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="5" />
<option name="METHOD_PARAMETERS_WRAP" value="5" />
<option name="RESOURCE_LIST_WRAP" value="5" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<option name="THROWS_LIST_WRAP" value="1" />
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
<option name="THROWS_KEYWORD_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="2" />
<option name="BINARY_OPERATION_WRAP" value="1" />
<option name="TERNARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="KEEP_SIMPLE_BLOCKS_IN_ONE_LINE" value="true" />
<option name="KEEP_SIMPLE_METHODS_IN_ONE_LINE" value="true" />
<option name="KEEP_SIMPLE_LAMBDAS_IN_ONE_LINE" value="true" />
<option name="KEEP_SIMPLE_CLASSES_IN_ONE_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="5" />
<option name="ARRAY_INITIALIZER_WRAP" value="5" />
<option name="ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE" value="true" />
<option name="ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE" value="true" />
<option name="ASSIGNMENT_WRAP" value="1" />
<option name="WRAP_COMMENTS" value="true" />
<option name="ASSERT_STATEMENT_WRAP" value="1" />
<option name="WRAP_LONG_LINES" value="true" />
<option name="PARAMETER_ANNOTATION_WRAP" value="5" />
<option name="VARIABLE_ANNOTATION_WRAP" value="5" />
<option name="ENUM_CONSTANTS_WRAP" value="5" />
<option name="KEEP_BUILDER_METHODS_INDENTS" value="true" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="5" />
<option name="METHOD_PARAMETERS_WRAP" value="5" />
<option name="EXTENDS_LIST_WRAP" value="5" />
<option name="METHOD_CALL_CHAIN_WRAP" value="5" />
<option name="ASSIGNMENT_WRAP" value="5" />
<option name="PARAMETER_ANNOTATION_WRAP" value="5" />
<option name="VARIABLE_ANNOTATION_WRAP" value="5" />
<option name="ENUM_CONSTANTS_WRAP" value="5" />
</codeStyleSettings>
</code_scheme>
</component>

View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

16
AUTHORS.md Normal file
View File

@ -0,0 +1,16 @@
# waituntil Contributors / Authors
By adding their names to this document, contributors agree to license all of their
contributions and patches to the waituntil project [under the AGPL version 3 or later.](./LICENSE.md)
Contributors may choose to supply either their complete legal name, online pseudonym or both.
At least one is required.
The email, website and notes fields are optional but contributors are encouraged
to supply at least one reliable method of communication.
## Maintainer(s)
| full name | pseudonym | email | website | notes |
|-|:-:|-:|-:|-|
| Jonas Tobias Hopusch | jotoho | [contact@jotoho.de](mailto:contact@jotoho.de) | [www.jotoho.de](https://www.jotoho.de/) | original creator |

View File

@ -1,12 +1,38 @@
# waituntil
This simple tool doubles as a programming exercise for me, as I attempt to learn Kotlin from my perspective as a Java developer and a (hopefully) useful tool for personal use. I will expand this README with details as the project evolves.
A basic tool for delaying work in the terminal to a specific time. This software was originally
written in Kotlin and then recently ported to Java.
Usage:
```sh
java -jar ./waituntil.jar 10:30 ; reboot # Replace reboot with your command
```
The example above would make the program wait until half past ten AM before exiting and allowing
the next command to run. The timestamp can be passed in the formats `HH:MM` or `HH:MM:SS` and must
be in the 24-hour system. Passing dates is not supported but entering a time that has already passed
will make the software wait until that time on the following day.
## Contributing / Submitting Feedback
The [canonical home of this project](https://gitea.jotoho.de/jotoho/waituntil/) is
[on my personal Gitea-instance](https://gitea.jotoho.de/) but since it has registration
turned off, collaborating there is difficult.
If you have not been given an account on [gitea.jotoho.de](https://gitea.jotoho.de/)
then you can alternatively send me feedback, bug reports or patches [via email to
contact@jotoho.de](mailto:contact@jotoho.de).
Should that fail, there may be alternative ways to contact me listed on
[my personal website.](https://www.jotoho.de/)
In the future, I may also decide to create a mirror for this project on GitHub, gitlab.com or similar.
## Copyright / Licensing
```
waituntil - a tool for delaying command execution until the specified time
Copyright (C) 2021 Jonas Tobias Hopusch
Copyright (C) 2022 Jonas Tobias Hopusch
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as

View File

@ -1,55 +0,0 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Kotlin application project to get you started.
* For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
* User Manual available at https://docs.gradle.org/7.2/userguide/building_java_projects.html
*/
plugins {
// Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin.
id("org.jetbrains.kotlin.jvm") version "1.+"
// Apply the application plugin to add support for building a CLI application in Java.
application
}
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
dependencies {
// Align versions of all Kotlin components
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
// Use the Kotlin JDK 8 standard library.
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
// This dependency is used by the application.
implementation("com.google.guava:guava:30.1.1-jre")
// Use the Kotlin test library.
testImplementation("org.jetbrains.kotlin:kotlin-test")
// Use the Kotlin JUnit integration.
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
}
java {
sourceCompatibility = JavaVersion.VERSION_16
targetCompatibility = JavaVersion.VERSION_16
}
tasks {
compileKotlin {
kotlinOptions {
jvmTarget = "16"
}
}
}
application {
// Define the main class for the application.
mainClass.set("de.jotoho.waituntil.StartKt")
}

View File

@ -1,101 +0,0 @@
package de.jotoho.waituntil
import java.util.Locale
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
import java.util.TimeZone
import java.time.Instant
import java.time.LocalTime
import java.time.LocalDate
import java.time.ZonedDateTime
import java.time.temporal.ChronoUnit
// This file contains the main function and other utility function necessary for interpreting the terminal arguments.
// See README.md and LICENSE.md for license information
// Author: Jonas Tobias Hopusch (@jotoho)
val langGerman: String = Locale.GERMAN.getLanguage();
val applicationOutputLanguage: String = if (Locale.getDefault().getLanguage().equals(Locale.GERMAN.getLanguage()))
Locale.GERMAN.getLanguage()
else Locale.ENGLISH.getLanguage();
fun waitUntilTimeStamp(timestamp: ZonedDateTime) {
Thread.sleep(
Math.max(Instant.now().until(timestamp, ChronoUnit.MILLIS), 0)
);
val formattedTimeStamp: String = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
.withZone(TimeZone.getDefault().toZoneId())
.format(Instant.now());
when (applicationOutputLanguage) {
langGerman -> System.err.println("Erfolgreich bis $formattedTimeStamp gewartet!");
else -> {
System.err.println("Successfully waited until $formattedTimeStamp");
}
}
}
fun calculateAndAnnounceTargetTime(userTimeInputRaw: String): ZonedDateTime {
val userTimeInputRelative = LocalTime.parse(userTimeInputRaw);
val userTimeInputAbsolute = ZonedDateTime.of(LocalDate.now(), userTimeInputRelative, TimeZone.getDefault().toZoneId());
val userTimeInputFinal = if (Instant.now().isBefore(userTimeInputAbsolute.toInstant())) userTimeInputAbsolute else userTimeInputAbsolute.plusDays(1);
val formattedTimeStamp = userTimeInputFinal.format(
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
);
when (applicationOutputLanguage) {
langGerman -> System.err.println("Dieses Program wird bis zum $formattedTimeStamp warten.");
else -> {
println("WaitUntil will suspend until $formattedTimeStamp");
}
}
return userTimeInputFinal;
}
fun main(args: Array<String>) {
val optionDictionary = mapOf(Pair("-h", "--help"));
val options = HashSet<String>();
val words = HashSet<String>();
for (arg in args) {
if (arg.startsWith("--")) {
options.add(arg.substring(startIndex=2))
}
else if (arg.startsWith('-')) {
val translation = optionDictionary.get(arg);
if (translation != null)
options.add(translation.substring(startIndex=2));
else
System.err.println("Short-hand '$arg' does not exist. Ignoring!");
}
else
words.add(arg);
}
if (options.contains("help")) {
when (applicationOutputLanguage) {
langGerman -> println("Hilfe kommt noch. (Nicht implementiert)");
else -> {
println("Help is yet to come. (Not implemented)");
}
}
}
else if (words.size == 1) {
val target = calculateAndAnnounceTargetTime(words.iterator().next());
waitUntilTimeStamp(target);
}
else {
when (applicationOutputLanguage) {
langGerman -> System.err.println("FATAL: Es wurde exact ein nicht-flag Argument erwartet. (${words.size} erhalten)");
else -> {
System.err.println("FATAL: Expected one non-flag argument. (Got ${words.size})");
}
}
System.exit(1);
}
}

View File

@ -1,14 +0,0 @@
/*
* This Kotlin source file was generated by the Gradle 'init' task.
*/
package de.jotoho.waituntil
import kotlin.test.Test
import kotlin.test.assertNotNull
class AppTest {
@Test fun appHasAGreeting() {
val classUnderTest = App()
assertNotNull(classUnderTest.greeting, "app should have a greeting")
}
}

53
build.gradle.kts Normal file
View File

@ -0,0 +1,53 @@
import java.io.ByteArrayOutputStream
import java.io.OutputStream
plugins {
// Apply the application plugin to add support for building a CLI application in Java.
application
java
id("com.github.johnrengelman.shadow") version "7.1.2"
}
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
dependencies {
implementation(group = "commons-cli", name = "commons-cli", version = "1.5.0")
}
fun versionBanner(): String {
val os = ByteArrayOutputStream()
project.exec {
commandLine = "git describe --tags --always --dirty --abbrev".split(" ")
standardOutput = os
errorOutput = OutputStream.nullOutputStream()
}
return String(os.toByteArray()).trim()
}
group = "de.jotoho"
version = versionBanner()
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
tasks.jar {
manifest {
attributes("Implementation-Title" to project.name,
"Implementation-Version" to project.version,
"Main-Class" to "de.jotoho.waituntil.Main"
//"Main-Module" to "de.jotoho.waituntil.main"
)
}
}
application {
// Define the main class for the application.
mainClass.set("de.jotoho.waituntil.Main")
//mainModule.set("de.jotoho.waituntil.main")
}

View File

@ -1,3 +0,0 @@
#!/bin/sh
kotlinc app/src/main/kotlin/de/jotoho/waituntil/start.kt -jvm-target 16 -include-runtime -d waituntil.jar

View File

@ -0,0 +1 @@
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip

3
run.sh
View File

@ -1,3 +0,0 @@
#!/bin/sh
java -jar waituntil.jar $*

View File

@ -7,5 +7,4 @@
* in the user manual at https://docs.gradle.org/7.2/userguide/multi_project_builds.html
*/
rootProject.name = "de.jotoho.waituntil"
include("app")
rootProject.name = "waituntil"

View File

@ -0,0 +1,39 @@
package de.jotoho.waituntil;
/*
waituntil - a tool for delaying command execution until the specified time
Copyright (C) 2022 Jonas Tobias Hopusch
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
final class AppOptions {
public final Option help = Option.builder()
.argName("h")
.longOpt("help")
.desc("Shows this help message and exits")
.build();
public final Option version = Option.builder()
.argName("v")
.longOpt("version")
.desc("Shows version information and exits")
.build();
public final Options options = new Options().addOption(help)
.addOption(version);
}

View File

@ -0,0 +1,30 @@
package de.jotoho.waituntil;
/*
waituntil - a tool for delaying command execution until the specified time
Copyright (C) 2022 Jonas Tobias Hopusch
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import java.util.Locale;
public record GlobalConf() {
public static final String langGerman = "de";
public static final String applicationOutputLanguage = (Locale.getDefault()
.getLanguage()
.equals(Locale.GERMAN.getLanguage()))
? Locale.GERMAN.getLanguage()
: Locale.ENGLISH.getLanguage();
}

View File

@ -0,0 +1,115 @@
package de.jotoho.waituntil;
/*
waituntil - a tool for delaying command execution until the specified time
Copyright (C) 2022 Jonas Tobias Hopusch
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import static de.jotoho.waituntil.GlobalConf.applicationOutputLanguage;
import static java.lang.System.Logger.Level;
// This file contains the main function and other utility function necessary
// for interpreting the terminal arguments.
// See README.md and LICENSE.md for license information
// Author: Jonas Tobias Hopusch (@jotoho)
public final class Main {
private static final System.Logger logger = System.getLogger("main");
private static void printVersionInformation() {
final var thisPackage = Main.class.getPackage();
final var appVersion = thisPackage.getImplementationVersion() != null
? thisPackage.getImplementationVersion()
: "version unknown";
System.out.println("waituntil " + appVersion);
System.out.println("""
Project Repository: https://gitea.jotoho.de/jotoho/waituntil
This program is free software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.""");
}
private static void printHelpInformation() {
switch (applicationOutputLanguage) {
case GlobalConf.langGerman -> logger.log(Level.ERROR,
"Hilfe kommt noch. (Nicht " +
"implementiert)");
default -> logger.log(Level.ERROR, "Help is yet to come. (Not implemented)");
}
}
private static CommandLine parseArgs(final Options options, final String[] args)
throws ParseException {
return DefaultParser.builder()
.setStripLeadingAndTrailingQuotes(true)
.build()
.parse(options, args);
}
public synchronized static void main(final String[] args) {
// Retrieve defined CLI options
final var appOptions = new AppOptions();
try {
// Parse CLI
final var parsedArguments = parseArgs(appOptions.options, args);
final var userData = parsedArguments.getArgs();
// Differentiate between usage scenarios
if (parsedArguments.hasOption(appOptions.help)) {
printHelpInformation();
} else if (parsedArguments.hasOption(appOptions.version)) {
printVersionInformation();
} else if (userData.length == 0) {
switch (applicationOutputLanguage) {
case GlobalConf.langGerman -> logger.log(Level.ERROR,
"Es wurde keine Uhrzeit " +
"angegeben.");
default -> logger.log(Level.ERROR, "No target time was provided.");
}
System.exit(1);
} else if (userData.length > 1) {
switch (applicationOutputLanguage) {
case GlobalConf.langGerman -> logger.log(Level.ERROR,
"Zu viele Argumente " +
"wurden angegeben.");
default -> logger.log(Level.ERROR, "Too many arguments provided.");
}
System.exit(1);
} else {
final var target = TimeCalculator.calculateAndAnnounceTargetTime(userData[0]);
Sleep.waitUntilTimeStamp(target);
}
} catch (final ParseException e) {
System.getLogger("main")
.log(Level.ERROR,
"Parsing of arguments failed and the program cannot continue.",
e);
System.exit(1);
}
}
}

View File

@ -0,0 +1,53 @@
package de.jotoho.waituntil;
/*
waituntil - a tool for delaying command execution until the specified time
Copyright (C) 2022 Jonas Tobias Hopusch
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import java.time.Instant;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.ChronoUnit;
import java.util.TimeZone;
import static java.lang.System.Logger.Level;
public final class Sleep {
public static void waitUntilTimeStamp(ZonedDateTime timestamp) {
try {
Thread.sleep(Math.max(0,
Instant.now()
.until(timestamp, ChronoUnit.MILLIS)));
} catch (final InterruptedException ignored) {
}
final String formattedTimeStamp = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
.withZone(TimeZone.getDefault()
.toZoneId())
.format(Instant.now());
final String msg = switch (GlobalConf.applicationOutputLanguage) {
case GlobalConf.langGerman -> "Erfolgreich bis %s gewartet!";
default -> "Successfully waited until %s";
};
final String msgWithData = msg.formatted(formattedTimeStamp);
System.getLogger("sleep")
.log(Level.INFO, msgWithData);
}
}

View File

@ -0,0 +1,58 @@
package de.jotoho.waituntil;
/*
waituntil - a tool for delaying command execution until the specified time
Copyright (C) 2022 Jonas Tobias Hopusch
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.TimeZone;
import static java.lang.System.Logger.Level;
public final class TimeCalculator {
public static ZonedDateTime calculateAndAnnounceTargetTime(final String userTimeInputRaw) {
final var userTimeInputRelative = LocalTime.parse(userTimeInputRaw);
final var userTimeInputAbsolute = ZonedDateTime.of(LocalDate.now(),
userTimeInputRelative,
TimeZone.getDefault()
.toZoneId());
final var userTimeInputFinal = (Instant.now()
.isBefore(userTimeInputAbsolute.toInstant()))
? userTimeInputAbsolute
: userTimeInputAbsolute.plusDays(1);
final var formattedTimeStamp =
userTimeInputFinal.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG));
final String msg = switch (GlobalConf.applicationOutputLanguage) {
case GlobalConf.langGerman -> ("Dieses Program wird bis zum %s warten.").formatted(
formattedTimeStamp);
default -> "WaitUntil will suspend until %s".formatted(formattedTimeStamp);
};
System.getLogger("timecalculator")
.log(Level.INFO, msg);
return userTimeInputFinal;
}
}