Skip to content

Instantly share code, notes, and snippets.

@Zren
Created June 19, 2012 16:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Zren/2955111 to your computer and use it in GitHub Desktop.
Save Zren/2955111 to your computer and use it in GitHub Desktop.
Recursive CountDownTask (Rounds up into the future second when scheduling)
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
public class Test {
// Output:
// 1340122752000: 2:00 minutes.
// 1340122812000: 1:00 minutes.
// 1340122842000: 30 seconds.
// 1340122852000: 20 seconds.
// 1340122862000: 10 seconds.
// 1340122867000: 5 seconds.
// 1340122868000: 4 seconds.
// 1340122869000: 3 seconds.
// 1340122870000: 2 seconds.
// 1340122871000: 1 seconds.
// 1340122872000: DONE!
public static void main(String[] args) throws Exception {
Timer timer = new Timer();
long start = System.currentTimeMillis();
long end = start + TimeUnit.MINUTES.toMillis(2);
timer.schedule(new CountDownTask(timer, start, end), 0);
}
/**
*
* @param msg
* @param args
*/
public static void println(String msg, Object... args) {
System.out.println(String.format(msg, args));
}
}
class CountDownTask extends TimerTask {
enum State {
DONE(0, "'DONE!'"),
SECONDS_1(TimeUnit.SECONDS.toMillis(1), "s 'seconds'."),
SECONDS_5(TimeUnit.SECONDS.toMillis(5), "s 'seconds'."),
SECONDS_10(TimeUnit.SECONDS.toMillis(10), "s 'seconds'."),
SECONDS_30(TimeUnit.SECONDS.toMillis(30), "s 'seconds'."),
MINUTES_1(TimeUnit.MINUTES.toMillis(1), "m:ss 'minutes'."),
MINUTES_5(TimeUnit.MINUTES.toMillis(5), "m:ss 'minutes'."),
MINUTES_10(TimeUnit.MINUTES.toMillis(10), "m:ss 'minutes'."),
MINUTES_30(TimeUnit.MINUTES.toMillis(30), "m:ss 'minutes'."),
HOURS_1(TimeUnit.HOURS.toMillis(1), "k:mm:ss 'hours'."),
DAYS_1(TimeUnit.DAYS.toMillis(1), "d 'days'."),
INFINITY(Long.MAX_VALUE, "'Infinity'");
private long timeDuration;
private String dateFormatString;
private State(long timeDuration, String dateFormatString) {
this.timeDuration = timeDuration;
this.dateFormatString = dateFormatString;
}
public long getTimeDuration() {
return timeDuration;
}
public String getDateFormatString() {
return dateFormatString;
}
}
Timer timer;
long startTime;
long endTime;
long now;
public CountDownTask(Timer timer, long startTime, long endTime) {
this.timer = timer;
this.startTime = ceilToSecond(startTime);
this.endTime = ceilToSecond(endTime);
}
public void run() {
now = System.currentTimeMillis();
now = ceilToSecond(now);
State currentState = getState(timeLeft());
SimpleDateFormat sdf = new SimpleDateFormat(currentState.getDateFormatString());
String msg = sdf.format(new Date(timeLeft()));
System.out.format("%d: %s%n", now, msg);
long nextMsgAt = timeLeft() - currentState.getTimeDuration();
// nextMsgAt = nextMsgAt / 1000 * 1000; // floor - rememove Millis
int stateIndex = currentState.ordinal();
if (stateIndex > 0) {
State nextState = State.values()[stateIndex - 1];
if (nextMsgAt < nextState.getTimeDuration()) {
nextMsgAt = timeLeft() - nextState.getTimeDuration();
}
long delayToNextMsg = timeLeft() - nextMsgAt;
timer.schedule(new CountDownTask(timer, startTime, endTime), delayToNextMsg);
}
}
// Ceil the current time to seconds to undesired looks (1:59, 1:29, ...)
public static long ceilToSecond(long t) {
return (t / 1000 + (t % 1000 > 0 ? 1 : 0)) * 1000;
}
public long timeLeft() {
return timeLeftTill(endTime);
}
public long timeLeftTill(long t) {
return t - now;
}
public static State getState(long timeLeft) {
for (State currentState : State.values()) {
int stateIndex = currentState.ordinal();
if (stateIndex >= State.values().length)
break;
State nextState = State.values()[stateIndex + 1];
if (nextState.getTimeDuration() > timeLeft)
return currentState;
}
return State.INFINITY;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment