mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-12-24 01:58:28 +01:00
Make use of Instant / Duration classes where possible for time handling
This commit is contained in:
parent
6e64f80c81
commit
96c53091d0
@ -40,6 +40,7 @@ import net.luckperms.api.node.types.WeightNode;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
@ -162,8 +163,8 @@ public interface Node {
|
||||
/**
|
||||
* Gets the time when this node will expire.
|
||||
*
|
||||
* @return the {@link Instant} when this node will expire, or null if it
|
||||
* doesn't have an expiry time
|
||||
* @return the {@link Instant} when this node will expire, or
|
||||
* {@code null} if it doesn't have an expiry time
|
||||
*/
|
||||
@Nullable Instant getExpiry();
|
||||
|
||||
@ -176,6 +177,17 @@ public interface Node {
|
||||
*/
|
||||
boolean hasExpired();
|
||||
|
||||
/**
|
||||
* Gets the time until this node will expire.
|
||||
*
|
||||
* <p>Returns {@code null} if the node doesn't have an expiry time,
|
||||
* and a {@link Duration#isNegative() negative} duration if it has already expired.</p>
|
||||
*
|
||||
* @return the duration until the nodes expiry
|
||||
* @since 5.1
|
||||
*/
|
||||
@Nullable Duration getExpiryDuration();
|
||||
|
||||
/**
|
||||
* Gets the contexts required for this node to apply.
|
||||
*
|
||||
|
@ -32,6 +32,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -85,7 +86,20 @@ public interface NodeBuilder<N extends ScopedNode<N, B>, B extends NodeBuilder<N
|
||||
/**
|
||||
* Sets the time when the node should expire.
|
||||
*
|
||||
* <p>The expiry timestamp is calculated relative to the current
|
||||
* <p>The expiry time is calculated relative to the current
|
||||
* system time.</p>
|
||||
*
|
||||
* @param duration how long the node should be added for
|
||||
* @return the builder
|
||||
* @see Node#getExpiry()
|
||||
* @since 5.1
|
||||
*/
|
||||
@NonNull B expiry(@Nullable TemporalAmount duration);
|
||||
|
||||
/**
|
||||
* Sets the time when the node should expire.
|
||||
*
|
||||
* <p>The expiry time is calculated relative to the current
|
||||
* system time.</p>
|
||||
*
|
||||
* @param duration how long the node should be added for
|
||||
|
@ -42,6 +42,7 @@ import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@ -81,7 +82,7 @@ public class LPBukkitBootstrap extends JavaPlugin implements LuckPermsBootstrap
|
||||
/**
|
||||
* The time when the plugin was enabled
|
||||
*/
|
||||
private long startTime;
|
||||
private Instant startTime;
|
||||
|
||||
// load/enable latches
|
||||
private final CountDownLatch loadLatch = new CountDownLatch(1);
|
||||
@ -149,7 +150,7 @@ public class LPBukkitBootstrap extends JavaPlugin implements LuckPermsBootstrap
|
||||
return;
|
||||
}
|
||||
|
||||
this.startTime = System.currentTimeMillis();
|
||||
this.startTime = Instant.now();
|
||||
try {
|
||||
this.plugin.enable();
|
||||
|
||||
@ -192,7 +193,7 @@ public class LPBukkitBootstrap extends JavaPlugin implements LuckPermsBootstrap
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStartupTime() {
|
||||
public Instant getStartupTime() {
|
||||
return this.startTime;
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ import net.md_5.bungee.api.plugin.Plugin;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@ -72,7 +73,7 @@ public class LPBungeeBootstrap extends Plugin implements LuckPermsBootstrap {
|
||||
/**
|
||||
* The time when the plugin was enabled
|
||||
*/
|
||||
private long startTime;
|
||||
private Instant startTime;
|
||||
|
||||
// load/enable latches
|
||||
private final CountDownLatch loadLatch = new CountDownLatch(1);
|
||||
@ -119,7 +120,7 @@ public class LPBungeeBootstrap extends Plugin implements LuckPermsBootstrap {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
this.startTime = System.currentTimeMillis();
|
||||
this.startTime = Instant.now();
|
||||
try {
|
||||
this.plugin.enable();
|
||||
} finally {
|
||||
@ -150,7 +151,7 @@ public class LPBungeeBootstrap extends Plugin implements LuckPermsBootstrap {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStartupTime() {
|
||||
public Instant getStartupTime() {
|
||||
return this.startTime;
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@ import net.luckperms.api.context.DefaultContextKeys;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
@ -92,6 +93,10 @@ public class LoggedAction implements Action {
|
||||
return Instant.ofEpochSecond(this.timestamp);
|
||||
}
|
||||
|
||||
public Duration getDurationSince() {
|
||||
return Duration.between(getTimestamp(), Instant.now());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Source getSource() {
|
||||
return this.source;
|
||||
|
@ -72,6 +72,6 @@ public class ApiPlatform implements Platform, PluginMetadata {
|
||||
|
||||
@Override
|
||||
public @NonNull Instant getStartTime() {
|
||||
return Instant.ofEpochMilli(this.plugin.getBootstrap().getStartupTime());
|
||||
return this.plugin.getBootstrap().getStartupTime();
|
||||
}
|
||||
}
|
||||
|
@ -32,13 +32,16 @@ import me.lucko.luckperms.common.context.contextset.MutableContextSetImpl;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.storage.misc.DataConstraints;
|
||||
import me.lucko.luckperms.common.util.DateParser;
|
||||
import me.lucko.luckperms.common.util.DurationParser;
|
||||
|
||||
import net.luckperms.api.context.DefaultContextKeys;
|
||||
import net.luckperms.api.context.ImmutableContextSet;
|
||||
import net.luckperms.api.context.MutableContextSet;
|
||||
import net.luckperms.api.model.data.TemporaryNodeMergeStrategy;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
@ -100,29 +103,29 @@ public class ArgumentParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static long parseDuration(int index, List<String> args) throws ArgumentException {
|
||||
long duration;
|
||||
public static Duration parseDuration(int index, List<String> args) throws ArgumentException {
|
||||
String input = args.get(index);
|
||||
Duration duration;
|
||||
|
||||
try {
|
||||
duration = Long.parseLong(args.get(index));
|
||||
long number = Long.parseLong(input);
|
||||
Instant now = Instant.now().truncatedTo(ChronoUnit.SECONDS);
|
||||
duration = Duration.between(now, Instant.ofEpochSecond(number));
|
||||
} catch (NumberFormatException e) {
|
||||
try {
|
||||
duration = DateParser.parseDate(args.get(index), true);
|
||||
duration = DurationParser.parseDuration(input);
|
||||
} catch (IllegalArgumentException e1) {
|
||||
throw new InvalidDateException(args.get(index));
|
||||
throw new InvalidDateException(input);
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldExpire(duration)) {
|
||||
if (duration.isNegative()) {
|
||||
throw new PastDateException();
|
||||
}
|
||||
|
||||
return duration;
|
||||
}
|
||||
|
||||
private static boolean shouldExpire(long unixTime) {
|
||||
return unixTime < (System.currentTimeMillis() / 1000L);
|
||||
}
|
||||
|
||||
public static TemporaryNodeMergeStrategy parseTemporaryModifier(String s) {
|
||||
switch (s.toLowerCase()) {
|
||||
case "accumulate":
|
||||
|
@ -55,6 +55,7 @@ import net.luckperms.api.model.data.DataType;
|
||||
import net.luckperms.api.model.data.TemporaryNodeMergeStrategy;
|
||||
import net.luckperms.api.node.ChatMetaType;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
public class MetaAddTempChatMeta extends SharedSubCommand {
|
||||
@ -80,7 +81,7 @@ public class MetaAddTempChatMeta extends SharedSubCommand {
|
||||
|
||||
int priority = ArgumentParser.parsePriority(0, args);
|
||||
String meta = ArgumentParser.parseString(1, args);
|
||||
long duration = ArgumentParser.parseDuration(2, args);
|
||||
Duration duration = ArgumentParser.parseDuration(2, args);
|
||||
TemporaryNodeMergeStrategy modifier = ArgumentParser.parseTemporaryModifier(3, args).orElseGet(() -> plugin.getConfiguration().get(ConfigKeys.TEMPORARY_ADD_BEHAVIOUR));
|
||||
MutableContextSet context = ArgumentParser.parseContext(3, args, plugin);
|
||||
|
||||
@ -93,9 +94,9 @@ public class MetaAddTempChatMeta extends SharedSubCommand {
|
||||
DataMutateResult.WithMergedNode ret = holder.setNode(DataType.NORMAL, this.type.builder(meta, priority).expiry(duration).withContext(context).build(), modifier);
|
||||
|
||||
if (ret.getResult().wasSuccessful()) {
|
||||
duration = ret.getMergedNode().getExpiry().getEpochSecond();
|
||||
duration = ret.getMergedNode().getExpiryDuration();
|
||||
|
||||
TextComponent.Builder builder = Message.ADD_TEMP_CHATMETA_SUCCESS.asComponent(plugin.getLocaleManager(), holder.getFormattedDisplayName(), this.type.name().toLowerCase(), meta, priority, DurationFormatter.LONG.formatDateDiff(duration), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)).toBuilder();
|
||||
TextComponent.Builder builder = Message.ADD_TEMP_CHATMETA_SUCCESS.asComponent(plugin.getLocaleManager(), holder.getFormattedDisplayName(), this.type.name().toLowerCase(), meta, priority, DurationFormatter.LONG.format(duration), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)).toBuilder();
|
||||
HoverEvent event = HoverEvent.showText(TextUtils.fromLegacy(
|
||||
"¥3Raw " + this.type.name().toLowerCase() + ": ¥r" + meta,
|
||||
'¥'
|
||||
|
@ -57,6 +57,7 @@ import net.luckperms.api.node.Node;
|
||||
import net.luckperms.api.node.NodeEqualityPredicate;
|
||||
import net.luckperms.api.node.NodeType;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
public class MetaSetTemp extends SharedSubCommand {
|
||||
@ -73,7 +74,7 @@ public class MetaSetTemp extends SharedSubCommand {
|
||||
|
||||
String key = args.get(0);
|
||||
String value = args.get(1);
|
||||
long duration = ArgumentParser.parseDuration(2, args);
|
||||
Duration duration = ArgumentParser.parseDuration(2, args);
|
||||
TemporaryNodeMergeStrategy modifier = ArgumentParser.parseTemporaryModifier(3, args).orElseGet(() -> plugin.getConfiguration().get(ConfigKeys.TEMPORARY_ADD_BEHAVIOUR));
|
||||
MutableContextSet context = ArgumentParser.parseContext(3, args, plugin);
|
||||
|
||||
@ -92,9 +93,9 @@ public class MetaSetTemp extends SharedSubCommand {
|
||||
}
|
||||
|
||||
holder.removeIf(DataType.NORMAL, context, NodeType.META.predicate(n -> n.hasExpiry() && n.getMetaKey().equalsIgnoreCase(key)), false);
|
||||
duration = holder.setNode(DataType.NORMAL, node, modifier).getMergedNode().getExpiry().getEpochSecond();
|
||||
duration = holder.setNode(DataType.NORMAL, node, modifier).getMergedNode().getExpiryDuration();
|
||||
|
||||
TextComponent.Builder builder = Message.SET_META_TEMP_SUCCESS.asComponent(plugin.getLocaleManager(), key, value, holder.getFormattedDisplayName(), DurationFormatter.LONG.formatDateDiff(duration), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)).toBuilder();
|
||||
TextComponent.Builder builder = Message.SET_META_TEMP_SUCCESS.asComponent(plugin.getLocaleManager(), key, value, holder.getFormattedDisplayName(), DurationFormatter.LONG.format(duration), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)).toBuilder();
|
||||
HoverEvent event = HoverEvent.showText(TextUtils.fromLegacy(
|
||||
TextUtils.joinNewline("¥3Raw key: ¥r" + key, "¥3Raw value: ¥r" + value),
|
||||
'¥'
|
||||
|
@ -58,6 +58,7 @@ import net.luckperms.api.model.data.TemporaryNodeMergeStrategy;
|
||||
import net.luckperms.api.node.ChatMetaType;
|
||||
import net.luckperms.api.query.QueryOptions;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.OptionalInt;
|
||||
|
||||
@ -84,7 +85,7 @@ public class MetaSetTempChatMeta extends SharedSubCommand {
|
||||
|
||||
int priority = ArgumentParser.parseIntOrElse(0, args, Integer.MIN_VALUE);
|
||||
String meta;
|
||||
long duration;
|
||||
Duration duration;
|
||||
TemporaryNodeMergeStrategy modifier;
|
||||
MutableContextSet context;
|
||||
|
||||
@ -133,9 +134,9 @@ public class MetaSetTempChatMeta extends SharedSubCommand {
|
||||
DataMutateResult.WithMergedNode ret = holder.setNode(DataType.NORMAL, this.type.builder(meta, priority).expiry(duration).withContext(context).build(), modifier);
|
||||
|
||||
if (ret.getResult().wasSuccessful()) {
|
||||
duration = ret.getMergedNode().getExpiry().getEpochSecond();
|
||||
duration = ret.getMergedNode().getExpiryDuration();
|
||||
|
||||
TextComponent.Builder builder = Message.ADD_TEMP_CHATMETA_SUCCESS.asComponent(plugin.getLocaleManager(), holder.getFormattedDisplayName(), this.type.name().toLowerCase(), meta, priority, DurationFormatter.LONG.formatDateDiff(duration), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)).toBuilder();
|
||||
TextComponent.Builder builder = Message.ADD_TEMP_CHATMETA_SUCCESS.asComponent(plugin.getLocaleManager(), holder.getFormattedDisplayName(), this.type.name().toLowerCase(), meta, priority, DurationFormatter.LONG.format(duration), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)).toBuilder();
|
||||
HoverEvent event = HoverEvent.showText(TextUtils.fromLegacy(
|
||||
"¥3Raw " + this.type.name().toLowerCase() + ": ¥r" + meta,
|
||||
'¥'
|
||||
|
@ -53,6 +53,7 @@ import net.luckperms.api.model.data.DataMutateResult;
|
||||
import net.luckperms.api.model.data.DataType;
|
||||
import net.luckperms.api.model.data.TemporaryNodeMergeStrategy;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
public class ParentAddTemp extends SharedSubCommand {
|
||||
@ -68,7 +69,7 @@ public class ParentAddTemp extends SharedSubCommand {
|
||||
}
|
||||
|
||||
String groupName = ArgumentParser.parseName(0, args);
|
||||
long duration = ArgumentParser.parseDuration(1, args);
|
||||
Duration duration = ArgumentParser.parseDuration(1, args);
|
||||
TemporaryNodeMergeStrategy modifier = ArgumentParser.parseTemporaryModifier(2, args).orElseGet(() -> plugin.getConfiguration().get(ConfigKeys.TEMPORARY_ADD_BEHAVIOUR));
|
||||
MutableContextSet context = ArgumentParser.parseContext(2, args, plugin);
|
||||
|
||||
@ -93,8 +94,8 @@ public class ParentAddTemp extends SharedSubCommand {
|
||||
DataMutateResult.WithMergedNode ret = holder.setNode(DataType.NORMAL, Inheritance.builder(group.getName()).expiry(duration).withContext(context).build(), modifier);
|
||||
|
||||
if (ret.getResult().wasSuccessful()) {
|
||||
duration = ret.getMergedNode().getExpiry().getEpochSecond();
|
||||
Message.SET_TEMP_INHERIT_SUCCESS.send(sender, holder.getFormattedDisplayName(), group.getFormattedDisplayName(), DurationFormatter.LONG.formatDateDiff(duration), MessageUtils.contextSetToString(plugin.getLocaleManager(), context));
|
||||
duration = ret.getMergedNode().getExpiryDuration();
|
||||
Message.SET_TEMP_INHERIT_SUCCESS.send(sender, holder.getFormattedDisplayName(), group.getFormattedDisplayName(), DurationFormatter.LONG.format(duration), MessageUtils.contextSetToString(plugin.getLocaleManager(), context));
|
||||
|
||||
LoggedAction.build().source(sender).target(holder)
|
||||
.description("parent", "addtemp", group.getName(), duration, context)
|
||||
|
@ -115,7 +115,7 @@ public class ParentInfo extends SharedSubCommand {
|
||||
for (InheritanceNode node : content) {
|
||||
String s = "&3> &a" + node.getGroupName() + MessageUtils.getAppendableNodeContextString(plugin.getLocaleManager(), node);
|
||||
if (node.hasExpiry()) {
|
||||
s += "\n&2 expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiry().getEpochSecond());
|
||||
s += "\n&2 expires in " + DurationFormatter.LONG.format(node.getExpiryDuration());
|
||||
}
|
||||
|
||||
TextComponent message = TextUtils.fromLegacy(s, TextUtils.AMPERSAND_CHAR).toBuilder().applyDeep(makeFancy(holder, label, node)).build();
|
||||
|
@ -115,7 +115,7 @@ public class PermissionInfo extends SharedSubCommand {
|
||||
for (Node node : content) {
|
||||
String s = "&3> " + (node.getValue() ? "&a" : "&c") + node.getKey() + (sender.isConsole() ? " &7(" + node.getValue() + "&7)" : "") + MessageUtils.getAppendableNodeContextString(plugin.getLocaleManager(), node);
|
||||
if (node.hasExpiry()) {
|
||||
s += "\n&2- expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiry().getEpochSecond());
|
||||
s += "\n&2- expires in " + DurationFormatter.LONG.format(node.getExpiryDuration());
|
||||
}
|
||||
|
||||
TextComponent message = TextUtils.fromLegacy(s, TextUtils.AMPERSAND_CHAR).toBuilder().applyDeep(makeFancy(holder, label, node)).build();
|
||||
|
@ -54,6 +54,7 @@ import net.luckperms.api.model.data.TemporaryNodeMergeStrategy;
|
||||
import net.luckperms.api.node.Node;
|
||||
import net.luckperms.api.node.types.InheritanceNode;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
public class PermissionSetTemp extends SharedSubCommand {
|
||||
@ -70,7 +71,7 @@ public class PermissionSetTemp extends SharedSubCommand {
|
||||
|
||||
String node = ArgumentParser.parseString(0, args);
|
||||
boolean value = ArgumentParser.parseBoolean(1, args);
|
||||
long duration = ArgumentParser.parseDuration(2, args);
|
||||
Duration duration = ArgumentParser.parseDuration(2, args);
|
||||
TemporaryNodeMergeStrategy modifier = ArgumentParser.parseTemporaryModifier(3, args).orElseGet(() -> plugin.getConfiguration().get(ConfigKeys.TEMPORARY_ADD_BEHAVIOUR));
|
||||
MutableContextSet context = ArgumentParser.parseContext(3, args, plugin);
|
||||
|
||||
@ -93,8 +94,8 @@ public class PermissionSetTemp extends SharedSubCommand {
|
||||
DataMutateResult.WithMergedNode result = holder.setNode(DataType.NORMAL, builtNode, modifier);
|
||||
|
||||
if (result.getResult().wasSuccessful()) {
|
||||
duration = result.getMergedNode().getExpiry().getEpochSecond();
|
||||
Message.SETPERMISSION_TEMP_SUCCESS.send(sender, node, value, holder.getFormattedDisplayName(), DurationFormatter.LONG.formatDateDiff(duration), MessageUtils.contextSetToString(plugin.getLocaleManager(), context));
|
||||
duration = result.getMergedNode().getExpiryDuration();
|
||||
Message.SETPERMISSION_TEMP_SUCCESS.send(sender, node, value, holder.getFormattedDisplayName(), DurationFormatter.LONG.format(duration), MessageUtils.contextSetToString(plugin.getLocaleManager(), context));
|
||||
|
||||
LoggedAction.build().source(sender).target(holder)
|
||||
.description("permission", "settemp", node, value, duration, context)
|
||||
|
@ -84,7 +84,7 @@ public class GroupInfo extends SubCommand<Group> {
|
||||
Message.INFO_TEMP_PARENT_HEADER.send(sender);
|
||||
for (InheritanceNode node : tempParents) {
|
||||
Message.INFO_PARENT_ENTRY.send(sender, node.getGroupName(), MessageUtils.getAppendableNodeContextString(plugin.getLocaleManager(), node));
|
||||
Message.INFO_PARENT_ENTRY_EXPIRY.send(sender, DurationFormatter.LONG.formatDateDiff(node.getExpiry().getEpochSecond()));
|
||||
Message.INFO_PARENT_ENTRY_EXPIRY.send(sender, DurationFormatter.LONG.format(node.getExpiryDuration()));
|
||||
}
|
||||
}
|
||||
return CommandResult.SUCCESS;
|
||||
|
@ -157,7 +157,7 @@ public class GroupListMembers extends SubCommand<Group> {
|
||||
return "";
|
||||
}
|
||||
|
||||
return " &8(&7expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiry().getEpochSecond()) + "&8)";
|
||||
return " &8(&7expires in " + DurationFormatter.LONG.format(node.getExpiryDuration()) + "&8)";
|
||||
}
|
||||
|
||||
private static Consumer<ComponentBuilder<? ,?>> makeFancy(String holderName, HolderType holderType, String label, HeldNode<?> perm, LuckPermsPlugin plugin) {
|
||||
|
@ -94,12 +94,10 @@ public class LogGroupHistory extends SubCommand<Log> {
|
||||
String name = ((Action) entries.values().stream().findAny().get()).getTarget().getName();
|
||||
Message.LOG_HISTORY_GROUP_HEADER.send(sender, name, page, maxPage);
|
||||
|
||||
long now = System.currentTimeMillis() / 1000L;
|
||||
for (Map.Entry<Integer, LoggedAction> e : entries.entrySet()) {
|
||||
long time = e.getValue().getTimestamp().getEpochSecond();
|
||||
Message.LOG_ENTRY.send(sender,
|
||||
e.getKey(),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format(now - time),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format(e.getValue().getDurationSince()),
|
||||
e.getValue().getSourceFriendlyString(),
|
||||
Character.toString(LoggedAction.getTypeCharacter(((Action) e.getValue()).getTarget().getType())),
|
||||
e.getValue().getTargetFriendlyString(),
|
||||
|
@ -106,12 +106,10 @@ public class LogRecent extends SubCommand<Log> {
|
||||
Message.LOG_RECENT_HEADER.send(sender, page, maxPage);
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis() / 1000L;
|
||||
for (Map.Entry<Integer, LoggedAction> e : entries.entrySet()) {
|
||||
long time = e.getValue().getTimestamp().getEpochSecond();
|
||||
Message.LOG_ENTRY.send(sender,
|
||||
e.getKey(),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format(now - time),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format(e.getValue().getDurationSince()),
|
||||
e.getValue().getSourceFriendlyString(),
|
||||
Character.toString(LoggedAction.getTypeCharacter(((Action) e.getValue()).getTarget().getType())),
|
||||
e.getValue().getTargetFriendlyString(),
|
||||
|
@ -93,12 +93,10 @@ public class LogSearch extends SubCommand<Log> {
|
||||
SortedMap<Integer, LoggedAction> entries = log.getPage(page, ENTRIES_PER_PAGE);
|
||||
Message.LOG_SEARCH_HEADER.send(sender, query, page, maxPage);
|
||||
|
||||
long now = System.currentTimeMillis() / 1000L;
|
||||
for (Map.Entry<Integer, LoggedAction> e : entries.entrySet()) {
|
||||
long time = e.getValue().getTimestamp().getEpochSecond();
|
||||
Message.LOG_ENTRY.send(sender,
|
||||
e.getKey(),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format(now - time),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format(e.getValue().getDurationSince()),
|
||||
e.getValue().getSourceFriendlyString(),
|
||||
Character.toString(LoggedAction.getTypeCharacter(((Action) e.getValue()).getTarget().getType())),
|
||||
e.getValue().getTargetFriendlyString(),
|
||||
|
@ -94,12 +94,10 @@ public class LogTrackHistory extends SubCommand<Log> {
|
||||
String name = ((Action) entries.values().stream().findAny().get()).getTarget().getName();
|
||||
Message.LOG_HISTORY_TRACK_HEADER.send(sender, name, page, maxPage);
|
||||
|
||||
long now = System.currentTimeMillis() / 1000L;
|
||||
for (Map.Entry<Integer, LoggedAction> e : entries.entrySet()) {
|
||||
long time = e.getValue().getTimestamp().getEpochSecond();
|
||||
Message.LOG_ENTRY.send(sender,
|
||||
e.getKey(),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format(now - time),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format(e.getValue().getDurationSince()),
|
||||
e.getValue().getSourceFriendlyString(),
|
||||
Character.toString(LoggedAction.getTypeCharacter(((Action) e.getValue()).getTarget().getType())),
|
||||
e.getValue().getTargetFriendlyString(),
|
||||
|
@ -87,12 +87,10 @@ public class LogUserHistory extends SubCommand<Log> {
|
||||
String name = ((Action) entries.values().stream().findAny().get()).getTarget().getName();
|
||||
Message.LOG_HISTORY_USER_HEADER.send(sender, name, page, maxPage);
|
||||
|
||||
long now = System.currentTimeMillis() / 1000L;
|
||||
for (Map.Entry<Integer, LoggedAction> e : entries.entrySet()) {
|
||||
long time = e.getValue().getTimestamp().getEpochSecond();
|
||||
Message.LOG_ENTRY.send(sender,
|
||||
e.getKey(),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format(now - time),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format(e.getValue().getDurationSince()),
|
||||
e.getValue().getSourceFriendlyString(),
|
||||
Character.toString(LoggedAction.getTypeCharacter(((Action) e.getValue()).getTarget().getType())),
|
||||
e.getValue().getTargetFriendlyString(),
|
||||
|
@ -312,7 +312,7 @@ public class ApplyEditsCommand extends SingleCommand {
|
||||
|
||||
private static String formatNode(LocaleManager localeManager, Node n) {
|
||||
return n.getKey() + " &7(" + (n.getValue() ? "&a" : "&c") + n.getValue() + "&7)" + MessageUtils.getAppendableNodeContextString(localeManager, n) +
|
||||
(n.hasExpiry() ? " &7(" + DurationFormatter.CONCISE.formatDateDiff(n.getExpiry().getEpochSecond()) + ")" : "");
|
||||
(n.hasExpiry() ? " &7(" + DurationFormatter.CONCISE.format(n.getExpiryDuration()) + ")" : "");
|
||||
}
|
||||
|
||||
private static <T> Map.Entry<Set<T>, Set<T>> diff(Set<T> before, Set<T> after) {
|
||||
|
@ -41,6 +41,8 @@ import me.lucko.luckperms.common.util.Predicates;
|
||||
import net.luckperms.api.context.ImmutableContextSet;
|
||||
import net.luckperms.api.extension.Extension;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -80,7 +82,7 @@ public class InfoCommand extends SingleCommand {
|
||||
staticContext.isEmpty() ? "None" : MessageUtils.contextSetToString(plugin.getLocaleManager(), staticContext),
|
||||
plugin.getBootstrap().getPlayerCount(),
|
||||
plugin.getConnectionListener().getUniqueConnections().size(),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format((System.currentTimeMillis() - plugin.getBootstrap().getStartupTime()) / 1000L),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format(Duration.between(plugin.getBootstrap().getStartupTime(), Instant.now())),
|
||||
plugin.getUserManager().getAll().size(),
|
||||
plugin.getGroupManager().getAll().size(),
|
||||
plugin.getTrackManager().getAll().size()
|
||||
|
@ -165,7 +165,7 @@ public class SearchCommand extends SingleCommand {
|
||||
return "";
|
||||
}
|
||||
|
||||
return " &8(&7expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiry().getEpochSecond()) + "&8)";
|
||||
return " &8(&7expires in " + DurationFormatter.LONG.format(node.getExpiryDuration()) + "&8)";
|
||||
}
|
||||
|
||||
private static Consumer<ComponentBuilder<?, ?>> makeFancy(String holderName, HolderType holderType, String label, HeldNode<?> perm, LuckPermsPlugin plugin) {
|
||||
|
@ -95,7 +95,7 @@ public class UserInfo extends SubCommand<User> {
|
||||
Message.INFO_TEMP_PARENT_HEADER.send(sender);
|
||||
for (InheritanceNode node : tempParents) {
|
||||
Message.INFO_PARENT_ENTRY.send(sender, node.getGroupName(), MessageUtils.getAppendableNodeContextString(plugin.getLocaleManager(), node));
|
||||
Message.INFO_PARENT_ENTRY_EXPIRY.send(sender, DurationFormatter.LONG.formatDateDiff(node.getExpiry().getEpochSecond()));
|
||||
Message.INFO_PARENT_ENTRY_EXPIRY.send(sender, DurationFormatter.LONG.format(node.getExpiryDuration()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -440,7 +440,7 @@ public abstract class PermissionHolder {
|
||||
switch (mergeStrategy) {
|
||||
case ADD_NEW_DURATION_TO_EXISTING: {
|
||||
// Create a new Node with the same properties, but add the expiry dates together
|
||||
long newExpiry = otherMatch.getExpiry().plus(Duration.between(Instant.now(), node.getExpiry())).getEpochSecond();
|
||||
Instant newExpiry = otherMatch.getExpiry().plus(Duration.between(Instant.now(), node.getExpiry()));
|
||||
newNode = node.toBuilder().expiry(newExpiry).build();
|
||||
break;
|
||||
}
|
||||
|
@ -40,7 +40,9 @@ import net.luckperms.api.node.types.PermissionNode;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -113,7 +115,18 @@ public abstract class AbstractNode<N extends ScopedNode<N, B>, B extends NodeBui
|
||||
|
||||
@Override
|
||||
public boolean hasExpired() {
|
||||
return hasExpiry() && this.expireAt < System.currentTimeMillis() / 1000L;
|
||||
Instant expiry = getExpiry();
|
||||
return expiry != null && expiry.isBefore(Instant.now());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Duration getExpiryDuration() {
|
||||
Instant expiry = getExpiry();
|
||||
if (expiry == null) {
|
||||
return null;
|
||||
}
|
||||
Instant now = Instant.now().truncatedTo(ChronoUnit.SECONDS);
|
||||
return Duration.between(now, expiry);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -37,8 +37,11 @@ import net.luckperms.api.node.metadata.NodeMetadataKey;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
@ -93,6 +96,16 @@ public abstract class AbstractNodeBuilder<N extends ScopedNode<N, B>, B extends
|
||||
return (B) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull B expiry(@Nullable TemporalAmount duration) {
|
||||
if (duration == null) {
|
||||
return clearExpiry();
|
||||
}
|
||||
|
||||
this.expireAt = Instant.now().truncatedTo(ChronoUnit.SECONDS).plus(duration).getEpochSecond();
|
||||
return (B) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull B clearExpiry() {
|
||||
this.expireAt = 0L;
|
||||
|
@ -28,8 +28,6 @@ package me.lucko.luckperms.common.node.comparator;
|
||||
import net.luckperms.api.node.Node;
|
||||
import net.luckperms.api.node.types.PermissionNode;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class NodeComparator implements Comparator<Node> {
|
||||
@ -65,8 +63,7 @@ public class NodeComparator implements Comparator<Node> {
|
||||
}
|
||||
|
||||
if (o1.hasExpiry()) {
|
||||
// note vvv
|
||||
result = -Long.compare(ChronoUnit.MILLIS.between(Instant.now(), o1.getExpiry()), ChronoUnit.MILLIS.between(Instant.now(), o2.getExpiry()));
|
||||
result = o1.getExpiry().compareTo(o2.getExpiry());
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
|
@ -61,6 +61,8 @@ import net.luckperms.api.LuckPerms;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@ -198,7 +200,8 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
||||
// perform any platform-specific final setup tasks
|
||||
performFinalSetup();
|
||||
|
||||
getLogger().info("Successfully enabled. (took " + (System.currentTimeMillis() - getBootstrap().getStartupTime()) + "ms)");
|
||||
Duration timeTaken = Duration.between(getBootstrap().getStartupTime(), Instant.now());
|
||||
getLogger().info("Successfully enabled. (took " + timeTaken.toMillis() + "ms)");
|
||||
}
|
||||
|
||||
public final void disable() {
|
||||
|
@ -35,6 +35,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@ -99,7 +100,7 @@ public interface LuckPermsBootstrap {
|
||||
*
|
||||
* @return the enable time
|
||||
*/
|
||||
long getStartupTime();
|
||||
Instant getStartupTime();
|
||||
|
||||
/**
|
||||
* Gets the platform type this instance of LuckPerms is running on.
|
||||
|
@ -1,135 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.util;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Translates unix timestamps / durations into a readable format
|
||||
*
|
||||
* @author khobbits, drtshock, vemacs
|
||||
* see: https://github.com/drtshock/Essentials/blob/2.x/Essentials/src/com/earth2me/essentials/utils/DateUtil.java
|
||||
*/
|
||||
public final class DateParser {
|
||||
private DateParser() {}
|
||||
|
||||
private static final Pattern TIME_PATTERN = Pattern.compile(Stream.of("y", "mo", "w", "d", "h", "m").map(i -> "(?:([0-9]+)\\s*" + i + "[a-z]*[,\\s]*)?").collect(Collectors.joining()) + "(?:([0-9]+)\\s*(?:s[a-z]*)?)?", Pattern.CASE_INSENSITIVE);
|
||||
private static final int MAX_YEARS = 100000;
|
||||
|
||||
/**
|
||||
* Converts a time string to a unix timestamp
|
||||
*
|
||||
* @param time the time string
|
||||
* @param future if the date is in the future, as opposed to the past
|
||||
* @return a unix timestamp
|
||||
* @throws IllegalArgumentException if the date input was invalid
|
||||
*/
|
||||
public static long parseDate(String time, boolean future) throws IllegalArgumentException {
|
||||
Matcher matcher = TIME_PATTERN.matcher(time);
|
||||
int years = 0, months = 0, weeks = 0, days = 0, hours = 0, minutes = 0, seconds = 0;
|
||||
|
||||
boolean found = false;
|
||||
while (matcher.find()) {
|
||||
if (matcher.group() == null || matcher.group().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < matcher.groupCount(); i++) {
|
||||
if (matcher.group(i) != null && !matcher.group(i).isEmpty()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
if (matcher.group(1) != null && !matcher.group(1).isEmpty()) {
|
||||
years = Integer.parseInt(matcher.group(1));
|
||||
}
|
||||
if (matcher.group(2) != null && !matcher.group(2).isEmpty()) {
|
||||
months = Integer.parseInt(matcher.group(2));
|
||||
}
|
||||
if (matcher.group(3) != null && !matcher.group(3).isEmpty()) {
|
||||
weeks = Integer.parseInt(matcher.group(3));
|
||||
}
|
||||
if (matcher.group(4) != null && !matcher.group(4).isEmpty()) {
|
||||
days = Integer.parseInt(matcher.group(4));
|
||||
}
|
||||
if (matcher.group(5) != null && !matcher.group(5).isEmpty()) {
|
||||
hours = Integer.parseInt(matcher.group(5));
|
||||
}
|
||||
if (matcher.group(6) != null && !matcher.group(6).isEmpty()) {
|
||||
minutes = Integer.parseInt(matcher.group(6));
|
||||
}
|
||||
if (matcher.group(7) != null && !matcher.group(7).isEmpty()) {
|
||||
seconds = Integer.parseInt(matcher.group(7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
Calendar c = new GregorianCalendar();
|
||||
if (years > 0) {
|
||||
if (years > MAX_YEARS) {
|
||||
years = MAX_YEARS;
|
||||
}
|
||||
c.add(Calendar.YEAR, years * (future ? 1 : -1));
|
||||
}
|
||||
if (months > 0) {
|
||||
c.add(Calendar.MONTH, months * (future ? 1 : -1));
|
||||
}
|
||||
if (weeks > 0) {
|
||||
c.add(Calendar.WEEK_OF_YEAR, weeks * (future ? 1 : -1));
|
||||
}
|
||||
if (days > 0) {
|
||||
c.add(Calendar.DAY_OF_MONTH, days * (future ? 1 : -1));
|
||||
}
|
||||
if (hours > 0) {
|
||||
c.add(Calendar.HOUR_OF_DAY, hours * (future ? 1 : -1));
|
||||
}
|
||||
if (minutes > 0) {
|
||||
c.add(Calendar.MINUTE, minutes * (future ? 1 : -1));
|
||||
}
|
||||
if (seconds > 0) {
|
||||
c.add(Calendar.SECOND, seconds * (future ? 1 : -1));
|
||||
}
|
||||
|
||||
Calendar max = new GregorianCalendar();
|
||||
max.add(Calendar.YEAR, 10);
|
||||
|
||||
if (c.after(max)) {
|
||||
c = max;
|
||||
}
|
||||
return c.getTimeInMillis() / 1000;
|
||||
}
|
||||
|
||||
}
|
@ -25,157 +25,109 @@
|
||||
|
||||
package me.lucko.luckperms.common.util;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
/**
|
||||
* Formats durations to a readable form
|
||||
*
|
||||
* @author khobbits, drtshock, vemacs
|
||||
* see: https://github.com/drtshock/Essentials/blob/2.x/Essentials/src/com/earth2me/essentials/utils/DateUtil.java
|
||||
*/
|
||||
public enum DurationFormatter {
|
||||
|
||||
LONG,
|
||||
CONCISE {
|
||||
private final String[] names = new String[]{"y", "y", "m", "m", "d", "d", "h", "h", "m", "m", "s", "s"};
|
||||
@Override
|
||||
protected String formatUnitPlural(ChronoUnit unit) {
|
||||
return String.valueOf(Character.toLowerCase(unit.name().charAt(0)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(Calendar from, Calendar to) {
|
||||
return dateDiff(from, to, 4, this.names, true);
|
||||
protected String formatUnitSingular(ChronoUnit unit) {
|
||||
return formatUnitPlural(unit);
|
||||
}
|
||||
},
|
||||
|
||||
CONCISE_LOW_ACCURACY {
|
||||
private final String[] names = new String[]{"y", "y", "m", "m", "d", "d", "h", "h", "m", "m", "s", "s"};
|
||||
|
||||
CONCISE_LOW_ACCURACY(3) {
|
||||
@Override
|
||||
public String format(Calendar from, Calendar to) {
|
||||
return dateDiff(from, to, 2, this.names, true);
|
||||
protected String formatUnitPlural(ChronoUnit unit) {
|
||||
return String.valueOf(Character.toLowerCase(unit.name().charAt(0)));
|
||||
}
|
||||
},
|
||||
|
||||
LONG {
|
||||
private final String[] names = new String[]{"year", "years", "month", "months", "day", "days", "hour", "hours", "minute", "minutes", "second", "seconds"};
|
||||
|
||||
@Override
|
||||
public String format(Calendar from, Calendar to) {
|
||||
return dateDiff(from, to, 4, this.names, false);
|
||||
protected String formatUnitSingular(ChronoUnit unit) {
|
||||
return formatUnitPlural(unit);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The calender type magic numbers to use when formatting
|
||||
*/
|
||||
private static final int[] CALENDAR_TYPES = new int[] {
|
||||
Calendar.YEAR,
|
||||
Calendar.MONTH,
|
||||
Calendar.DAY_OF_MONTH,
|
||||
Calendar.HOUR_OF_DAY,
|
||||
Calendar.MINUTE,
|
||||
Calendar.SECOND
|
||||
private final Unit[] units = new Unit[]{
|
||||
new Unit(ChronoUnit.YEARS),
|
||||
new Unit(ChronoUnit.MONTHS),
|
||||
new Unit(ChronoUnit.WEEKS),
|
||||
new Unit(ChronoUnit.DAYS),
|
||||
new Unit(ChronoUnit.HOURS),
|
||||
new Unit(ChronoUnit.MINUTES),
|
||||
new Unit(ChronoUnit.SECONDS)
|
||||
};
|
||||
|
||||
private static final int MAX_YEARS = 100000;
|
||||
private final int accuracy;
|
||||
|
||||
/**
|
||||
* Formats the difference between two dates
|
||||
*
|
||||
* @param from the start date
|
||||
* @param to the end date
|
||||
* @param maxAccuracy how accurate the output should be (how many sections it'll have)
|
||||
* @param names the names to use to format each of the corresponding {@link #CALENDAR_TYPES}
|
||||
* @return a formatted string
|
||||
*/
|
||||
private static String dateDiff(Calendar from, Calendar to, int maxAccuracy, String[] names, boolean concise) {
|
||||
if (to.equals(from)) {
|
||||
return "now";
|
||||
DurationFormatter() {
|
||||
this(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
DurationFormatter(int accuracy) {
|
||||
if (accuracy <= 0) {
|
||||
throw new IllegalArgumentException("accuracy must be >= 1");
|
||||
}
|
||||
this.accuracy = accuracy;
|
||||
}
|
||||
|
||||
protected String formatUnitPlural(ChronoUnit unit) {
|
||||
return " " + unit.name().toLowerCase();
|
||||
}
|
||||
|
||||
protected String formatUnitSingular(ChronoUnit unit) {
|
||||
String s = unit.name().toLowerCase();
|
||||
return " " + s.substring(0, s.length() - 1);
|
||||
}
|
||||
|
||||
private final class Unit {
|
||||
private final long duration;
|
||||
private final String stringPlural;
|
||||
private final String stringSingular;
|
||||
|
||||
Unit(ChronoUnit unit) {
|
||||
this.duration = unit.getDuration().getSeconds();
|
||||
this.stringPlural = formatUnitPlural(unit);
|
||||
this.stringSingular = formatUnitSingular(unit);
|
||||
}
|
||||
|
||||
boolean future = to.after(from);
|
||||
public String toString(long n) {
|
||||
return n == 1 ? this.stringSingular : this.stringPlural;
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int accuracy = 0;
|
||||
for (int i = 0; i < CALENDAR_TYPES.length; i++) {
|
||||
if (accuracy > maxAccuracy) {
|
||||
private String format(long seconds) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
int outputSize = 0;
|
||||
|
||||
for (Unit unit : this.units) {
|
||||
long n = seconds / unit.duration;
|
||||
if (n > 0) {
|
||||
seconds -= unit.duration * n;
|
||||
output.append(' ').append(n).append(unit.toString(n));
|
||||
outputSize++;
|
||||
}
|
||||
if (seconds <= 0 || outputSize >= this.accuracy) {
|
||||
break;
|
||||
}
|
||||
|
||||
int diff = dateDiff(CALENDAR_TYPES[i], from, to, future);
|
||||
if (diff > 0) {
|
||||
int plural = diff > 1 ? 1 : 0;
|
||||
String unit = names[i * 2 + plural];
|
||||
|
||||
sb.append(" ");
|
||||
sb.append(diff);
|
||||
if (!concise) {
|
||||
sb.append(" ");
|
||||
}
|
||||
sb.append(unit);
|
||||
|
||||
accuracy++;
|
||||
}
|
||||
}
|
||||
|
||||
if (sb.length() == 0) {
|
||||
return "now";
|
||||
if (output.length() == 0) {
|
||||
return "0" + this.units[this.units.length - 1].stringPlural;
|
||||
}
|
||||
|
||||
return sb.toString().trim();
|
||||
return output.substring(1);
|
||||
}
|
||||
|
||||
private static int dateDiff(int type, Calendar fromDate, Calendar toDate, boolean future) {
|
||||
int fromYear = fromDate.get(Calendar.YEAR);
|
||||
int toYear = toDate.get(Calendar.YEAR);
|
||||
if (Math.abs(fromYear - toYear) > MAX_YEARS) {
|
||||
toDate.set(Calendar.YEAR, fromYear + (future ? MAX_YEARS : -MAX_YEARS));
|
||||
}
|
||||
|
||||
int diff = 0;
|
||||
long savedDate = fromDate.getTimeInMillis();
|
||||
while ((future && !fromDate.after(toDate)) || (!future && !fromDate.before(toDate))) {
|
||||
savedDate = fromDate.getTimeInMillis();
|
||||
fromDate.add(type, future ? 1 : -1);
|
||||
diff++;
|
||||
}
|
||||
|
||||
diff--;
|
||||
fromDate.setTimeInMillis(savedDate);
|
||||
return diff;
|
||||
public String format(Duration duration) {
|
||||
return format(duration.getSeconds());
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the time difference between two dates
|
||||
*
|
||||
* @param from the start date
|
||||
* @param to the end date
|
||||
* @return the formatted duration string
|
||||
*/
|
||||
public abstract String format(Calendar from, Calendar to);
|
||||
|
||||
/**
|
||||
* Formats a duration, in seconds
|
||||
*
|
||||
* @param seconds the duration
|
||||
* @return the formatted duration string
|
||||
*/
|
||||
public String format(long seconds) {
|
||||
Calendar from = new GregorianCalendar();
|
||||
from.setTimeInMillis(0);
|
||||
|
||||
Calendar to = new GregorianCalendar();
|
||||
to.setTimeInMillis(seconds * 1000L);
|
||||
|
||||
return format(from, to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the duration between the current time and the given unix timestamp
|
||||
*
|
||||
* @param unixTimestamp the timestamp, in seconds
|
||||
* @return the formatted duration string
|
||||
*/
|
||||
public String formatDateDiff(long unixTimestamp) {
|
||||
long now = System.currentTimeMillis() / 1000L;
|
||||
return format(unixTimestamp - now);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.util;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Arrays;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Parses durations from a string format
|
||||
*/
|
||||
public final class DurationParser {
|
||||
private DurationParser() {}
|
||||
|
||||
private static final ChronoUnit[] UNITS = new ChronoUnit[]{
|
||||
ChronoUnit.YEARS,
|
||||
ChronoUnit.MONTHS,
|
||||
ChronoUnit.WEEKS,
|
||||
ChronoUnit.DAYS,
|
||||
ChronoUnit.HOURS,
|
||||
ChronoUnit.MINUTES,
|
||||
ChronoUnit.SECONDS
|
||||
};
|
||||
|
||||
private static final String PATTERN_STRING = Arrays.stream(UNITS)
|
||||
.limit(UNITS.length - 1) // skip seconds
|
||||
.map(unit -> {
|
||||
if (unit == ChronoUnit.MONTHS) {
|
||||
return "mo";
|
||||
}
|
||||
// use the first char as the abbreviation
|
||||
return String.valueOf(Character.toLowerCase(unit.name().charAt(0)));
|
||||
})
|
||||
.map(abbreviation -> "(?:([0-9]+)\\s*" + abbreviation + "[a-z]*[,\\s]*)?")
|
||||
.collect(Collectors.joining())
|
||||
.concat("(?:([0-9]+)\\s*(?:s[a-z]*)?)?");
|
||||
|
||||
private static final Pattern PATTERN = Pattern.compile(PATTERN_STRING, Pattern.CASE_INSENSITIVE);
|
||||
|
||||
public static Duration parseDuration(String input) throws IllegalArgumentException {
|
||||
Matcher matcher = PATTERN.matcher(input);
|
||||
|
||||
while (matcher.find()) {
|
||||
if (matcher.group() == null || matcher.group().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Duration duration = Duration.ZERO;
|
||||
for (int i = 0; i < UNITS.length; i++) {
|
||||
ChronoUnit unit = UNITS[i];
|
||||
int g = i + 1;
|
||||
|
||||
if (matcher.group(g) != null && !matcher.group(g).isEmpty()) {
|
||||
int n = Integer.parseInt(matcher.group(g));
|
||||
duration = duration.plus(n, unit);
|
||||
}
|
||||
}
|
||||
|
||||
return duration;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("unable to parse duration: " + input);
|
||||
}
|
||||
|
||||
}
|
@ -53,9 +53,10 @@ import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
@ -65,7 +66,7 @@ import java.util.zip.GZIPOutputStream;
|
||||
* Accepts and processes {@link VerboseEvent}, passed from the {@link VerboseHandler}.
|
||||
*/
|
||||
public class VerboseListener {
|
||||
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
|
||||
private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
|
||||
|
||||
// how much data should we store before stopping.
|
||||
private static final int DATA_TRUNCATION = 10000;
|
||||
@ -97,7 +98,7 @@ public class VerboseListener {
|
||||
.build();
|
||||
|
||||
// the time when the listener was first registered
|
||||
private final long startTime = System.currentTimeMillis();
|
||||
private final Instant startTime = Instant.now();
|
||||
// the sender to notify each time the listener processes a check which passes the filter
|
||||
private final Sender notifiedSender;
|
||||
// the filter
|
||||
@ -255,10 +256,9 @@ public class VerboseListener {
|
||||
public String uploadPasteData(BytebinClient bytebin) {
|
||||
// retrieve variables
|
||||
long now = System.currentTimeMillis();
|
||||
String startDate = DATE_FORMAT.format(new Date(this.startTime));
|
||||
String endDate = DATE_FORMAT.format(new Date(now));
|
||||
long secondsTaken = (now - this.startTime) / 1000L;
|
||||
String duration = DurationFormatter.CONCISE.format(secondsTaken);
|
||||
String startDate = DATE_FORMAT.format(this.startTime);
|
||||
String endDate = DATE_FORMAT.format(Instant.now());
|
||||
String duration = DurationFormatter.CONCISE.format(Duration.between(this.startTime, Instant.now()));
|
||||
boolean truncated = this.matchedCounter.get() > this.results.size();
|
||||
|
||||
JObject metadata = new JObject()
|
||||
|
@ -37,6 +37,7 @@ import cn.nukkit.plugin.PluginBase;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@ -70,7 +71,7 @@ public class LPNukkitBootstrap extends PluginBase implements LuckPermsBootstrap
|
||||
/**
|
||||
* The time when the plugin was enabled
|
||||
*/
|
||||
private long startTime;
|
||||
private Instant startTime;
|
||||
|
||||
// load/enable latches
|
||||
private final CountDownLatch loadLatch = new CountDownLatch(1);
|
||||
@ -117,7 +118,7 @@ public class LPNukkitBootstrap extends PluginBase implements LuckPermsBootstrap
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
this.startTime = System.currentTimeMillis();
|
||||
this.startTime = Instant.now();
|
||||
try {
|
||||
this.plugin.enable();
|
||||
} finally {
|
||||
@ -148,7 +149,7 @@ public class LPNukkitBootstrap extends PluginBase implements LuckPermsBootstrap
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStartupTime() {
|
||||
public Instant getStartupTime() {
|
||||
return this.startTime;
|
||||
}
|
||||
|
||||
|
@ -57,6 +57,7 @@ import org.spongepowered.api.scheduler.SynchronousExecutor;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@ -102,7 +103,7 @@ public class LPSpongeBootstrap implements LuckPermsBootstrap {
|
||||
/**
|
||||
* The time when the plugin was enabled
|
||||
*/
|
||||
private long startTime;
|
||||
private Instant startTime;
|
||||
|
||||
// load/enable latches
|
||||
private final CountDownLatch loadLatch = new CountDownLatch(1);
|
||||
@ -162,7 +163,7 @@ public class LPSpongeBootstrap implements LuckPermsBootstrap {
|
||||
|
||||
@Listener(order = Order.FIRST)
|
||||
public void onEnable(GamePreInitializationEvent event) {
|
||||
this.startTime = System.currentTimeMillis();
|
||||
this.startTime = Instant.now();
|
||||
try {
|
||||
this.plugin.load();
|
||||
} finally {
|
||||
@ -218,7 +219,7 @@ public class LPSpongeBootstrap implements LuckPermsBootstrap {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStartupTime() {
|
||||
public Instant getStartupTime() {
|
||||
return this.startTime;
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,7 @@ import org.slf4j.Logger;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@ -88,7 +89,7 @@ public class LPVelocityBootstrap implements LuckPermsBootstrap {
|
||||
/**
|
||||
* The time when the plugin was enabled
|
||||
*/
|
||||
private long startTime;
|
||||
private Instant startTime;
|
||||
|
||||
// load/enable latches
|
||||
private final CountDownLatch loadLatch = new CountDownLatch(1);
|
||||
@ -130,7 +131,7 @@ public class LPVelocityBootstrap implements LuckPermsBootstrap {
|
||||
|
||||
@Subscribe(order = PostOrder.FIRST)
|
||||
public void onEnable(ProxyInitializeEvent e) {
|
||||
this.startTime = System.currentTimeMillis();
|
||||
this.startTime = Instant.now();
|
||||
try {
|
||||
this.plugin.load();
|
||||
} finally {
|
||||
@ -173,7 +174,7 @@ public class LPVelocityBootstrap implements LuckPermsBootstrap {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStartupTime() {
|
||||
public Instant getStartupTime() {
|
||||
return this.startTime;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user