package de.skuzzle.polly.sdk.time; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import de.skuzzle.polly.sdk.eventlistener.DayChangedListener; /** * Used to obtain and set current polly system time using {@link TimeProvider} * instances. * @author Simon * @since 0.9.1 */ public final class Time { private static TimeProvider provider = new SystemTimeProvider(); private final static Collection<DayChangedListener> LISTENERS; private final static ScheduledExecutorService EXECUTOR; private final static long ONE_DAY = Milliseconds.fromDays(1); private static ScheduledFuture<?> future; static { LISTENERS = new ArrayList<DayChangedListener>(); EXECUTOR = Executors.newSingleThreadScheduledExecutor(); scheduleEventTimer(); } private synchronized final static void scheduleEventTimer() { if (future != null) { future.cancel(false); } final Date midnight = DateUtils.getDayAhead(1); long untilMidnight = midnight.getTime() - Time.currentTimeMillis(); future = EXECUTOR.scheduleAtFixedRate(new Runnable() { @Override public void run() { final long now = Time.currentTimeMillis(); for (final DayChangedListener listener : LISTENERS) { listener.dayChanged(now); } } }, untilMidnight, ONE_DAY, TimeUnit.MILLISECONDS); } /** * Sets a new {@link TimeProvider}. * @param timeProvider The provider to set. */ public final static void setProvider(TimeProvider timeProvider) { if (!timeProvider.equals(provider)) { scheduleEventTimer(); } provider = timeProvider; } /** * Gets the currently set {@link TimeProvider} * * @return The provider. */ public static TimeProvider getProvider() { return provider; } /** * Gets the current polly system time calculated by the time provider set with * {@link #setProvider(TimeProvider)}. By default, this method returns the same time * as {@link System#currentTimeMillis()}. * @return The current time as millisecond timestamp. */ public final static long currentTimeMillis() { return provider.currentTimeMillis(); } /** * Returns the current polly system time as a {@link Date} instance. * * @return The current time. */ public final static Date currentTime() { return new Date(currentTimeMillis()); } /** * Adds a listener that will be notified when the day changed. * * @param listenner The listener to add. */ public final static void addDayChangeListener(DayChangedListener listenner) { LISTENERS.add(listenner); } /** * Removes a DayChangedListener * * @param listener The listener to remove */ public final static void removeDayChangeListener(DayChangedListener listener) { LISTENERS.remove(listener); } private Time() {} }