Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shortened Timespans (again) #7001

Merged
merged 13 commits into from
Oct 13, 2024
37 changes: 27 additions & 10 deletions src/main/java/ch/njol/skript/util/Timespan.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,27 @@ public enum TimePeriod implements TemporalUnit {
YEAR(DAY.time * 365L);

private final Noun name;
private final Noun shortName;
private final long time;

TimePeriod(long time) {
this.name = new Noun("time." + this.name().toLowerCase(Locale.ENGLISH));
this.name = new Noun("time." + this.name().toLowerCase(Locale.ENGLISH) + ".full");
this.shortName = new Noun("time." + this.name().toLowerCase(Locale.ENGLISH) + ".short");
this.time = time;
}

public long getTime() {
return time;
}

public String getFullForm() {
return name.toString();
}

public String getShortForm() {
return shortName.toString();
}

@Override
public Duration getDuration() {
return Duration.ofMillis(time);
Expand Down Expand Up @@ -119,6 +129,8 @@ public void onLanguageChange() {
for (TimePeriod time : TimePeriod.values()) {
PARSE_VALUES.put(time.name.getSingular().toLowerCase(Locale.ENGLISH), time.getTime());
PARSE_VALUES.put(time.name.getPlural().toLowerCase(Locale.ENGLISH), time.getTime());
PARSE_VALUES.put(time.shortName.getSingular().toLowerCase(Locale.ENGLISH), time.getTime());
PARSE_VALUES.put(time.shortName.getPlural().toLowerCase(Locale.ENGLISH), time.getTime());
}
}
});
Expand All @@ -127,6 +139,7 @@ public void onLanguageChange() {
private static final Pattern TIMESPAN_PATTERN = Pattern.compile("^(\\d+):(\\d\\d)(:\\d\\d){0,2}(?<ms>\\.\\d{1,4})?$");
private static final Pattern TIMESPAN_NUMBER_PATTERN = Pattern.compile("^\\d+(\\.\\d+)?$");
private static final Pattern TIMESPAN_SPLIT_PATTERN = Pattern.compile("[:.]");
private static final Pattern SHORT_FORM_PATTERN = Pattern.compile("^(\\d+(?:\\.\\d+)?)([a-zA-Z]+)$");

private final long millis;

Expand All @@ -135,7 +148,7 @@ public static Timespan parse(String value) {
if (value.isEmpty())
return null;

long t = 0;
long totalMillis = 0;
boolean minecraftTime = false;
boolean isMinecraftTimeSet = false;

Expand All @@ -153,7 +166,7 @@ else if (length == 3 && !hasMs || length == 4) // HH:MM:SS[.ms]
offset = 1;

for (int i = 0; i < substring.length; i++) {
t += times[offset + i] * Utils.parseLong("" + substring[i]);
totalMillis += times[offset + i] * Utils.parseLong("" + substring[i]);
}
} else { // <number> minutes/seconds/.. etc
String[] substring = value.toLowerCase(Locale.ENGLISH).split("\\s+");
Expand Down Expand Up @@ -196,21 +209,25 @@ else if (length == 3 && !hasMs || length == 4) // HH:MM:SS[.ms]
if (sub.endsWith(","))
sub = sub.substring(0, sub.length() - 1);

Long d = PARSE_VALUES.get(sub.toLowerCase(Locale.ENGLISH));
if (d == null)
Matcher shortFormMatcher = SHORT_FORM_PATTERN.matcher(sub);
if (shortFormMatcher.matches()) {
amount = Double.parseDouble(shortFormMatcher.group(1));
sub = shortFormMatcher.group(2).toLowerCase(Locale.ENGLISH);
}

Long millis = PARSE_VALUES.get(sub.toLowerCase(Locale.ENGLISH));
if (millis == null)
return null;

if (minecraftTime && d != TimePeriod.TICK.time)
if (minecraftTime && millis != TimePeriod.TICK.time)
amount /= 72f;

t += Math.round(amount * d);
totalMillis += Math.round(amount * millis);

isMinecraftTimeSet = true;

}
}

return new Timespan(t);
return new Timespan(totalMillis);
}

public Timespan() {
Expand Down
36 changes: 27 additions & 9 deletions src/main/resources/lang/default.lang
Original file line number Diff line number Diff line change
Expand Up @@ -343,15 +343,33 @@ tree types:

# -- Time --
time:
millisecond: millisecond¦s
tick: tick¦s
second: second¦s
minute: minute¦s
hour: hour¦s
day: day¦s
week: week¦s
month: month¦s
year: year¦s
millisecond:
full: millisecond¦s
short: ms
tick:
full: tick¦s
short: t
second:
full: second¦s
short: s
minute:
full: minute¦s
short: m
hour:
full: hour¦s
short: h
day:
full: day¦s
short: d
week:
full: week¦s
short: w
month:
full: month¦s
short: mo
year:
full: year¦s
short: y
real: real, rl, irl
minecraft: mc, minecraft

Expand Down
84 changes: 84 additions & 0 deletions src/test/skript/tests/misc/timespans.sk
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
test "timespans":

set {_timespan} to 1 day
assert {_timespan} is a timespan with "Failed to parse '1 day'"
assert {_timespan} is 24 hours with "Failed to set variable to '1 day'"

set {_timespan} to 2 hours
assert {_timespan} is a timespan with "Failed to parse '2 hours'"
assert {_timespan} is 120 minutes with "Failed to set variable to '2 hours'"

set {_timespan} to 30 minutes
assert {_timespan} is a timespan with "Failed to parse '30 minutes'"
assert {_timespan} is 1800 seconds with "Failed to set variable to '30 minutes'"

set {_timespan} to 1d
assert {_timespan} is a timespan with "Failed to parse '1d'"
assert {_timespan} is 24 hours with "Failed to set variable to '1d'"

set {_timespan} to 2h
assert {_timespan} is a timespan with "Failed to parse '2h'"
assert {_timespan} is 120 minutes with "Failed to set variable to '2h'"

set {_timespan} to 30m
assert {_timespan} is a timespan with "Failed to parse '30m'"
assert {_timespan} is 1800 seconds with "Failed to set variable to '30m'"

# Comparisons with both long and short form
set {_timespan} to 30 minutes and 20s
assert {_timespan} is a timespan with "Failed to parse '30 minutes and 20s'"
assert {_timespan} is 30m and 20 seconds with "Failed to set variable to '30 minutes and 20s'"

set {_timespan} to 1 mo, 30 days, 12w, 20 minutes and 15s
assert {_timespan} is a timespan with "Failed to parse '1 mo, 30 days, 12w, 20 minutes and 15s'"
assert {_timespan} is 1 month, 30 days, 12 weeks, 20 minutes and 15 seconds with "Failed to set variable to '1 mo, 30 days, 12w, 20 minutes and 15s'"

set {_timespan} to 50 minutes and 45 seconds
assert {_timespan} is a timespan with "Failed to parse '50 minutes and 45 seconds'"
assert {_timespan} is 50m and 45s with "Failed to set variable to '50 minutes and 45 seconds'"

# Edge cases
set {_timespan} to 0.5d
assert {_timespan} is a timespan with "Failed to parse '0.5d'"
Asleeepp marked this conversation as resolved.
Show resolved Hide resolved
assert {_timespan} is 12 hours with "Failed to set variable to 0.5d"

set {_timespan} to 90m
assert {_timespan} is a timespan with "Failed to parse '90m'"
assert {_timespan} is 1.5 hours with "Failed to set variable to 90m"

set {_timespan} to 3600s
assert {_timespan} is a timespan with "Failed to parse '3600s'"
assert {_timespan} is 60 minutes with "Failed to set variable to '3600s'"

# decimal tests with long names and multiple units
set {_timespan} to 1.5 days
assert {_timespan} is a timespan with "Failed to parse '1.5 days'"
assert {_timespan} is 36 hours with "Failed to set variable to '1.5 days'"

set {_timespan} to 2.5 seconds
assert {_timespan} is a timespan with "Failed to parse '2.5 seconds'"
assert {_timespan} is 2500 milliseconds with "Failed to set variable to '2.5 seconds'"

set {_timespan} to 1.5 days and 2.5 seconds
assert {_timespan} is a timespan with "Failed to parse '1.5 days and 2.5 seconds'"
assert {_timespan} is 36 hours and 2.5 seconds with "Failed to set variable to '1.5 days and 2.5 seconds'"

# Add, remove, and clear tests
set {_timespan} to 1 day
add 2 hours to {_timespan}
assert {_timespan} is 26 hours with "Failed to add 2 hours to '1 day'"

set {_timespan} to 1 day
remove 2 hours from {_timespan}
assert {_timespan} is 22 hours with "Failed to remove 2 hours from '1 day'"

set {_timespan} to 1 day
clear {_timespan}
assert {_timespan} is not set with "Failed to clear timespan"

# overflow test
set {_timespan} to 9999999999 days
assert {_timespan} is a timespan with "Failed to parse large timespan"
assert {_timespan} is greater than 9999999998 days with "Failed to handle large timespan correctly"