diff --git a/core-java-modules/core-java-date-operations-2/pom.xml b/core-java-modules/core-java-date-operations-2/pom.xml
index 6b126a978b..155b8ad0b7 100644
--- a/core-java-modules/core-java-date-operations-2/pom.xml
+++ b/core-java-modules/core-java-date-operations-2/pom.xml
@@ -31,11 +31,18 @@
hirondelle-date4j
${hirondelle-date4j.version}
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
2.10
1.5.1
+ 3.14.0
\ No newline at end of file
diff --git a/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timer/DatabaseMigrationTask.java b/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timer/DatabaseMigrationTask.java
new file mode 100644
index 0000000000..322c1d2f4e
--- /dev/null
+++ b/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timer/DatabaseMigrationTask.java
@@ -0,0 +1,19 @@
+package com.baeldung.timer;
+
+import java.util.List;
+import java.util.TimerTask;
+
+public class DatabaseMigrationTask extends TimerTask {
+ private List oldDatabase;
+ private List newDatabase;
+
+ public DatabaseMigrationTask(List oldDatabase, List newDatabase) {
+ this.oldDatabase = oldDatabase;
+ this.newDatabase = newDatabase;
+ }
+
+ @Override
+ public void run() {
+ newDatabase.addAll(oldDatabase);
+ }
+}
diff --git a/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timer/NewsletterTask.java b/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timer/NewsletterTask.java
new file mode 100644
index 0000000000..16dd6c12ff
--- /dev/null
+++ b/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timer/NewsletterTask.java
@@ -0,0 +1,14 @@
+package com.baeldung.timer;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.TimerTask;
+
+public class NewsletterTask extends TimerTask {
+ @Override
+ public void run() {
+ System.out.println("Email sent at: "
+ + LocalDateTime.ofInstant(Instant.ofEpochMilli(scheduledExecutionTime()), ZoneId.systemDefault()));
+ }
+}
diff --git a/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timer/DatabaseMigrationTaskUnitTest.java b/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timer/DatabaseMigrationTaskUnitTest.java
new file mode 100644
index 0000000000..5f3ae63901
--- /dev/null
+++ b/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timer/DatabaseMigrationTaskUnitTest.java
@@ -0,0 +1,44 @@
+package com.baeldung.timer;
+
+import org.junit.jupiter.api.Test;
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.*;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class DatabaseMigrationTaskUnitTest {
+ @Test
+ void givenDatabaseMigrationTask_whenTimerScheduledForNowPlusTwoSeconds_thenDataMigratedAfterTwoSeconds() throws Exception {
+ List oldDatabase = Arrays.asList("Harrison Ford", "Carrie Fisher", "Mark Hamill");
+ List newDatabase = new ArrayList<>();
+
+ LocalDateTime twoSecondsLater = LocalDateTime.now().plusSeconds(2);
+ Date twoSecondsLaterAsDate = Date.from(twoSecondsLater.atZone(ZoneId.systemDefault()).toInstant());
+
+ new Timer().schedule(new DatabaseMigrationTask(oldDatabase, newDatabase), twoSecondsLaterAsDate);
+
+ while (LocalDateTime.now().isBefore(twoSecondsLater)) {
+ assertThat(newDatabase).isEmpty();
+ Thread.sleep(500);
+ }
+ assertThat(newDatabase).containsExactlyElementsOf(oldDatabase);
+ }
+
+ @Test
+ void givenDatabaseMigrationTask_whenTimerScheduledInTwoSeconds_thenDataMigratedAfterTwoSeconds() throws Exception {
+ List oldDatabase = Arrays.asList("Harrison Ford", "Carrie Fisher", "Mark Hamill");
+ List newDatabase = new ArrayList<>();
+
+ new Timer().schedule(new DatabaseMigrationTask(oldDatabase, newDatabase), 2000);
+
+ LocalDateTime twoSecondsLater = LocalDateTime.now().plusSeconds(2);
+
+ while (LocalDateTime.now().isBefore(twoSecondsLater)) {
+ assertThat(newDatabase).isEmpty();
+ Thread.sleep(500);
+ }
+ assertThat(newDatabase).containsExactlyElementsOf(oldDatabase);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timer/NewsletterTaskUnitTest.java b/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timer/NewsletterTaskUnitTest.java
new file mode 100644
index 0000000000..ffbe39c2bc
--- /dev/null
+++ b/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timer/NewsletterTaskUnitTest.java
@@ -0,0 +1,33 @@
+package com.baeldung.timer;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.Timer;
+
+class NewsletterTaskUnitTest {
+ private final Timer timer = new Timer();
+
+ @AfterEach
+ void afterEach() {
+ timer.cancel();
+ }
+
+ @Test
+ void givenNewsletterTask_whenTimerScheduledEachSecondFixedDelay_thenNewsletterSentEachSecond() throws Exception {
+ timer.schedule(new NewsletterTask(), 0, 1000);
+
+ for (int i = 0; i < 3; i++) {
+ Thread.sleep(1000);
+ }
+ }
+
+ @Test
+ void givenNewsletterTask_whenTimerScheduledEachSecondFixedRate_thenNewsletterSentEachSecond() throws Exception {
+ timer.scheduleAtFixedRate(new NewsletterTask(), 0, 1000);
+
+ for (int i = 0; i < 3; i++) {
+ Thread.sleep(1000);
+ }
+ }
+}
\ No newline at end of file