Skip to content

Instantly share code, notes, and snippets.

@james-d
Last active August 29, 2015 13:57
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 james-d/9686094 to your computer and use it in GitHub Desktop.
Save james-d/9686094 to your computer and use it in GitHub Desktop.
Java 8 Clock with convenient string bindings for "xxx ago" labels, with an example.
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.util.Duration;
public class Clock {
private final ReadOnlyObjectWrapper<LocalDateTime> time ;
private final List<ChronoUnit> units = Arrays.asList(
ChronoUnit.MILLENNIA,
ChronoUnit.CENTURIES,
ChronoUnit.YEARS,
ChronoUnit.MONTHS,
ChronoUnit.WEEKS,
ChronoUnit.DAYS,
ChronoUnit.HOURS,
ChronoUnit.MINUTES,
ChronoUnit.SECONDS
);
private final Timeline clockwork ;
public Clock(Duration tickInterval, boolean start) {
time = new ReadOnlyObjectWrapper<>(LocalDateTime.now());
clockwork = new Timeline(new KeyFrame(tickInterval, event -> time.set(LocalDateTime.now())));
clockwork.setCycleCount(Animation.INDEFINITE);
if (start) {
clockwork.play();
}
}
public Clock(Duration tickInterval) {
this(tickInterval, false);
}
public StringBinding getElapsedStringBinding(LocalDateTime start) {
return Bindings.createStringBinding(() ->
units.stream()
.filter(u -> start.plus(1, u).isBefore(time.get())) // ignore units where less than 1 unit has elapsed
.sorted(Comparator.reverseOrder()) // sort with biggest first
.findFirst() // get the first (biggest) unit
.map(u -> String.format("%d %s ago", u.between(start, time.get()), u)) // format as string
.orElse("Just now") // default if elapsed time is less than smallest unit
, time);
}
public StringBinding getElapsedStringBinding() {
return getElapsedStringBinding(LocalDateTime.now());
}
public StringBinding getTimeStringBinding(DateTimeFormatter formatter) {
return Bindings.createStringBinding(() -> formatter.format(time.get()), time);
}
public StringBinding getTimeStringBinding() {
return getTimeStringBinding(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM));
}
public ReadOnlyObjectProperty<LocalDateTime> timeProperty() {
return time ;
}
public LocalDateTime getTime() {
return time.get();
}
public void start() {
clockwork.play();
}
public void stop() {
clockwork.stop();
}
}
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class TimedItemDisplay extends Application {
@Override
public void start(Stage primaryStage) {
final Clock clock = new Clock(Duration.seconds(1), true);
final BorderPane root = new BorderPane();
final HBox controls = new HBox(5);
controls.setAlignment(Pos.CENTER);
controls.setPadding(new Insets(10));
final TextField itemField = new TextField();
itemField.setTooltip(new Tooltip("Type an item and press Enter"));
controls.getChildren().add(itemField);
final VBox items = new VBox(5);
itemField.setOnAction(event -> {
String text = itemField.getText();
Label label = new Label();
label.textProperty().bind(Bindings.format("%s (%s)", text, clock.getElapsedStringBinding()));
items.getChildren().add(label);
itemField.setText("");
});
final ScrollPane scroller = new ScrollPane();
scroller.setContent(items);
final Label currentTimeLabel = new Label();
currentTimeLabel.textProperty().bind(Bindings.format("Current time: %s", clock.getTimeStringBinding()));
root.setTop(controls);
root.setCenter(scroller);
root.setBottom(currentTimeLabel);
Scene scene = new Scene(root, 600, 400);
primaryStage.setTitle("Timed item display");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment