Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 27 additions & 63 deletions src/main/java/net/aboodyy/localtime/DateManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@

package net.aboodyy.localtime;

import org.bukkit.Bukkit;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import me.clip.placeholderapi.PlaceholderAPIPlugin;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;

Expand All @@ -35,22 +37,23 @@
import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.*;
import java.util.logging.Level;

public class DateManager implements Listener {

private final Map<UUID, String> timezones;
private final Map<String, String> cache;
private final Cache<String, String> cache;
private final ScheduledExecutorService executorService;
private int retryDelay;
private final int cacheExpirationMinutes = 1440; // Cache entries expire after 1440 minutes (1 Day)

public DateManager() {
this.timezones = new ConcurrentHashMap<>();
this.cache = new ConcurrentHashMap<>();
this.cache = CacheBuilder.newBuilder()
.expireAfterWrite(cacheExpirationMinutes, TimeUnit.MINUTES)
.build();
this.retryDelay = 5; // default to 5 seconds
this.executorService = Executors.newSingleThreadScheduledExecutor();

executorService.scheduleAtFixedRate(this::removeExpiredEntries, cacheExpirationMinutes, cacheExpirationMinutes, TimeUnit.MINUTES);
}

public String getDate(String format, String timezone) {
Expand All @@ -62,48 +65,10 @@ public String getDate(String format, String timezone) {
return dateFormat.format(date);
}

private boolean isCacheExpired(UUID uuid) {
String timestampStr = cache.get(uuid.toString() + "_timestamp");
if (timestampStr == null) {
return true;
}

long timestamp = Long.parseLong(timestampStr);
long currentTime = System.currentTimeMillis();
long expirationTime = cacheExpirationMinutes * 60 * 1000;

if ((currentTime - timestamp) >= expirationTime) {
timezones.remove(uuid); // Remove the player from the timezones map when cache expires
return true;
} else {
return false;
}
}

private void removeExpiredEntries() {
for (Map.Entry<String, String> entry : cache.entrySet()) {
if (entry.getKey().endsWith("_timestamp")) {
continue; // Skip keys with the "_timestamp" suffix
}

UUID uuid;
try {
uuid = UUID.fromString(entry.getKey());
} catch (IllegalArgumentException e) {
continue; // Skip non-UUID keys
}

if (isCacheExpired(uuid)) {
cache.remove(uuid.toString());
timezones.remove(uuid);
}
}
}

public CompletableFuture<String> getTimeZone(Player player) {
final String FAILED = "[LocalTime] Couldn't get " + player.getName() + "'s timezone. Will use default timezone.";

String cachedTimezone = cache.get(player.getUniqueId().toString());
String cachedTimezone = cache.getIfPresent(player.getUniqueId().toString());
if (cachedTimezone != null) {
return CompletableFuture.completedFuture(cachedTimezone);
}
Expand All @@ -114,15 +79,15 @@ public CompletableFuture<String> getTimeZone(Player player) {
}

InetSocketAddress address = player.getAddress();
timezone = TimeZone.getDefault().getID();

if (address == null) {
Bukkit.getLogger().info(FAILED);
PlaceholderAPIPlugin.getInstance().getLogger().log(Level.WARNING, FAILED);
timezone = TimeZone.getDefault().getID();
cache.put(player.getUniqueId().toString(), timezone);
return CompletableFuture.completedFuture(timezone);
}

final String timezoneFinal = timezone;
final String defaultTimezone = TimeZone.getDefault().getID();

CompletableFuture<String> futureTimezone = CompletableFuture.supplyAsync(() -> {
String result = "undefined";
int retries = 3;
Expand All @@ -135,51 +100,50 @@ public CompletableFuture<String> getTimeZone(Player player) {
connection.setReadTimeout(5000);
connection.setRequestProperty("User-Agent", "Mozilla/5.0");

// Use try-with-resources to automatically close the BufferedReader
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
result = bufferedReader.readLine();

if (result == null) {
result = "undefined";
} else {
cache.put(player.getUniqueId().toString(), result);
cache.put(player.getUniqueId().toString() + "_timestamp", String.valueOf(System.currentTimeMillis()));
}
break; // exit loop if successful
break;
}
} catch (Exception e) {
result = "undefined";
Bukkit.getLogger().warning("[LocalTime] Exception while getting timezone for player " + player.getName() + ": " + e.getMessage());
PlaceholderAPIPlugin.getInstance().getLogger().log(Level.WARNING, "[LocalTime] Exception while getting timezone for player " + player.getName() + ": " + e.getMessage(), e);
try {
Thread.sleep(retryDelay * 1000);
} catch (InterruptedException ignored) {}
}
}

if (result.equalsIgnoreCase("undefined")) {
Bukkit.getLogger().info(FAILED);
result = timezoneFinal;
PlaceholderAPIPlugin.getInstance().getLogger().log(Level.WARNING, FAILED);
result = defaultTimezone;
}

timezones.put(player.getUniqueId(), result);
return result;
}, executorService);


futureTimezone.exceptionally(ex -> {
Bukkit.getLogger().warning("[LocalTime] Exception while getting timezone for player " + player.getName() + ": " + ex.getMessage());
cache.put(player.getUniqueId().toString(), timezoneFinal);
timezones.put(player.getUniqueId(), timezoneFinal);
return timezoneFinal;
PlaceholderAPIPlugin.getInstance().getLogger().log(Level.WARNING, "[LocalTime] Exception while getting timezone for player " + player.getName() + ": " + ex.getMessage(), ex);
cache.put(player.getUniqueId().toString(), defaultTimezone);
timezones.put(player.getUniqueId(), defaultTimezone);
return defaultTimezone;
});

return CompletableFuture.completedFuture(timezoneFinal);
return futureTimezone;
}

public void clear() {
timezones.clear();
cache.clear();
cache.invalidateAll();
}
}


public void shutdown() {
this.executorService.shutdown();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public Map<String, Object> getDefaults() {
public void clear() {
dateManager.clear();
HandlerList.unregisterAll(dateManager);
dateManager.shutdown();
}

@Override
Expand Down