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 f60c7b7fc0..461ba70b62 100644 --- a/core-java-modules/core-java-date-operations-2/pom.xml +++ b/core-java-modules/core-java-date-operations-2/pom.xml @@ -30,11 +30,29 @@ hirondelle-date4j ${hirondelle-date4j.version} + + net.time4j + time4j-base + ${time4j-base.version} + + + net.time4j + time4j-sqlxml + ${time4j-sqlxml.version} + + + org.ocpsoft.prettytime + prettytime + ${prettytime.version} + 2.10 1.5.1 + 3.2.7.Final + 5.9 + 5.8 \ No newline at end of file diff --git a/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version7/TimeAgoCalculator.java b/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version7/TimeAgoCalculator.java new file mode 100644 index 0000000000..e09880f1ee --- /dev/null +++ b/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version7/TimeAgoCalculator.java @@ -0,0 +1,94 @@ +package com.baeldung.timeago.version7; + +import java.util.Date; +import java.util.TimeZone; + +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.joda.time.Period; +import org.joda.time.format.PeriodFormat; +import org.joda.time.format.PeriodFormatter; +import org.joda.time.format.PeriodFormatterBuilder; + +public class TimeAgoCalculator { + + public static String calculateTimeAgoByTimeGranularity(Date pastTime, TimeGranularity granularity) { + Date currentTime = new Date(); + long timeDifferenceInMillis = currentTime.getTime() - pastTime.getTime(); + return timeDifferenceInMillis / granularity.toMillis() + " " + granularity.name() + .toLowerCase() + " ago"; + } + + public static String calculateHumanFriendlyTimeAgo(Date pastTime) { + Date currentTime = new Date(); + long timeDifferenceInMillis = currentTime.getTime() - pastTime.getTime(); + if (timeDifferenceInMillis / TimeGranularity.DECADES.toMillis() > 0) + return "several decades ago"; + else if (timeDifferenceInMillis / TimeGranularity.YEARS.toMillis() > 0) + return "several years ago"; + else if (timeDifferenceInMillis / TimeGranularity.MONTHS.toMillis() > 0) + return "several months ago"; + else if (timeDifferenceInMillis / TimeGranularity.WEEKS.toMillis() > 0) + return "several weeks ago"; + else if (timeDifferenceInMillis / TimeGranularity.DAYS.toMillis() > 0) + return "several days ago"; + else if (timeDifferenceInMillis / TimeGranularity.HOURS.toMillis() > 0) + return "several hours ago"; + else if (timeDifferenceInMillis / TimeGranularity.MINUTES.toMillis() > 0) + return "several minutes ago"; + else + return "moments ago"; + } + + public static String calculateExactTimeAgoWithJodaTime(Date pastTime) { + Period period = new Period(new DateTime(pastTime.getTime()), new DateTime()); + PeriodFormatter formatter = new PeriodFormatterBuilder().appendYears() + .appendSuffix(" year ", " years ") + .appendSeparator("and ") + .appendMonths() + .appendSuffix(" month ", " months ") + .appendSeparator("and ") + .appendWeeks() + .appendSuffix(" week ", " weeks ") + .appendSeparator("and ") + .appendDays() + .appendSuffix(" day ", " days ") + .appendSeparator("and ") + .appendHours() + .appendSuffix(" hour ", " hours ") + .appendSeparator("and ") + .appendMinutes() + .appendSuffix(" minute ", " minutes ") + .appendSeparator("and ") + .appendSeconds() + .appendSuffix(" second", " seconds") + .toFormatter(); + return formatter.print(period); + } + + public static String calculateHumanFriendlyTimeAgoWithJodaTime(Date pastTime) { + Period period = new Period(new DateTime(pastTime.getTime()), new DateTime()); + if (period.getYears() != 0) + return "several years ago"; + else if (period.getMonths() != 0) + return "several months ago"; + else if (period.getWeeks() != 0) + return "several weeks ago"; + else if (period.getDays() != 0) + return "several days ago"; + else if (period.getHours() != 0) + return "several hours ago"; + else if (period.getMinutes() != 0) + return "several minutes ago"; + else + return "moments ago"; + } + + public static String calculateZonedTimeAgoWithJodaTime(Date pastTime, TimeZone zone) { + DateTimeZone dateTimeZone = DateTimeZone.forID(zone.getID()); + Period period = new Period(new DateTime(pastTime.getTime(), dateTimeZone), new DateTime(dateTimeZone)); + return PeriodFormat.getDefault() + .print(period); + } + +} diff --git a/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version7/TimeGranularity.java b/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version7/TimeGranularity.java new file mode 100644 index 0000000000..0cdb9729e2 --- /dev/null +++ b/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version7/TimeGranularity.java @@ -0,0 +1,41 @@ +package com.baeldung.timeago.version7; + +import java.util.concurrent.TimeUnit; + +public enum TimeGranularity { + SECONDS { + public long toMillis() { + return TimeUnit.SECONDS.toMillis(1); + } + }, MINUTES { + public long toMillis() { + return TimeUnit.MINUTES.toMillis(1); + } + }, HOURS { + public long toMillis() { + return TimeUnit.HOURS.toMillis(1); + } + }, DAYS { + public long toMillis() { + return TimeUnit.DAYS.toMillis(1); + } + }, WEEKS { + public long toMillis() { + return TimeUnit.DAYS.toMillis(7); + } + }, MONTHS { + public long toMillis() { + return TimeUnit.DAYS.toMillis(30); + } + }, YEARS { + public long toMillis() { + return TimeUnit.DAYS.toMillis(365); + } + }, DECADES { + public long toMillis() { + return TimeUnit.DAYS.toMillis(365 * 10); + } + }; + + public abstract long toMillis(); +} diff --git a/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version8/TimeAgoCalculator.java b/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version8/TimeAgoCalculator.java new file mode 100644 index 0000000000..392cfa54fa --- /dev/null +++ b/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version8/TimeAgoCalculator.java @@ -0,0 +1,44 @@ +package com.baeldung.timeago.version8; + +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.Period; +import java.time.ZoneId; +import java.util.Date; +import java.util.Locale; + +import org.ocpsoft.prettytime.PrettyTime; + +public class TimeAgoCalculator { + + public static String calculateTimeAgoWithPeriodAndDuration(LocalDateTime pastTime, ZoneId zone) { + Period period = Period.between(pastTime.toLocalDate(), LocalDate.now(zone)); + Duration duration = Duration.between(pastTime, LocalDateTime.now(zone)); + if (period.getYears() != 0) + return "several years ago"; + else if (period.getMonths() != 0) + return "several months ago"; + else if (period.getDays() != 0) + return "several days ago"; + else if (duration.toHours() != 0) + return "several hours ago"; + else if (duration.toMinutes() != 0) + return "several minutes ago"; + else if (duration.getSeconds() != 0) + return "several seconds ago"; + else + return "moments ago"; + } + + public static String calculateTimeAgoWithPrettyTime(Date pastTime) { + PrettyTime prettyTime = new PrettyTime(); + return prettyTime.format(pastTime); + } + + public static String calculateTimeAgoWithTime4J(Date pastTime, ZoneId zone, Locale locale) { + return net.time4j.PrettyTime.of(locale) + .printRelative(pastTime.toInstant(), zone); + } + +} diff --git a/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timeago/version7/TimeAgoCalculatorUnitTest.java b/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timeago/version7/TimeAgoCalculatorUnitTest.java new file mode 100644 index 0000000000..53975e2d83 --- /dev/null +++ b/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timeago/version7/TimeAgoCalculatorUnitTest.java @@ -0,0 +1,55 @@ +package com.baeldung.timeago.version7; + +import java.util.Date; + +import org.junit.Assert; +import org.junit.Test; + +public class TimeAgoCalculatorUnitTest { + + @Test + public void timeAgoByTimeGranularityTest() { + long DAY_IN_MILLIS = 1000 * 60 * 60 * 24; + Assert.assertEquals("5 seconds ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(System.currentTimeMillis() - (5 * 1000)), TimeGranularity.SECONDS)); + Assert.assertEquals("5 minutes ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(System.currentTimeMillis() - (5 * 60 * 1000)), TimeGranularity.MINUTES)); + Assert.assertEquals("5 hours ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(System.currentTimeMillis() - (5 * 60 * 60 * 1000)), TimeGranularity.HOURS)); + Assert.assertEquals("5 days ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS)), TimeGranularity.DAYS)); + Assert.assertEquals("5 months ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 30)), TimeGranularity.MONTHS)); + Assert.assertEquals("5 weeks ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 7)), TimeGranularity.WEEKS)); + Assert.assertEquals("5 years ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 365)), TimeGranularity.YEARS)); + Assert.assertEquals("5 decades ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 365 * 10)), TimeGranularity.DECADES)); + } + + @Test + public void humanFriendlyTimeAgoTest() { + long DAY_IN_MILLIS = 1000 * 60 * 60 * 24; + Assert.assertEquals("moments ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(System.currentTimeMillis() - (5 * 1000)))); + Assert.assertEquals("several minutes ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(System.currentTimeMillis() - (5 * 60 * 1000)))); + Assert.assertEquals("several hours ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(System.currentTimeMillis() - (5 * 60 * 60 * 1000)))); + Assert.assertEquals("several days ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS)))); + Assert.assertEquals("several months ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 30)))); + Assert.assertEquals("several weeks ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(System.currentTimeMillis() - (3 * DAY_IN_MILLIS * 7)))); + Assert.assertEquals("several years ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 365)))); + Assert.assertEquals("several decades ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 365 * 10)))); + } + + @Test + public void calculateExactTimeAgoWithJodaTimeTest() { + Assert.assertEquals("5 hours and 15 minutes and 3 seconds", TimeAgoCalculator.calculateExactTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (5 * 60 * 60 * 1000 + 15 * 60 * 1000 + 3 * 1000)))); + Assert.assertEquals("5 hours and 1 minute and 1 second", TimeAgoCalculator.calculateExactTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (5 * 60 * 60 * 1000 + 1 * 60 * 1000 + 1 * 1000)))); + Assert.assertEquals("2 days and 1 minute and 1 second", TimeAgoCalculator.calculateExactTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (2 * 24 * 60 * 60 * 1000 + 1 * 60 * 1000 + 1 * 1000)))); + } + + @Test + public void calculateHumanFriendlyTimeAgoWithJodaTimeTest() { + long DAY_IN_MILLIS = 1000 * 60 * 60 * 24; + Assert.assertEquals("moments ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (5 * 1000)))); + Assert.assertEquals("several minutes ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (5 * 60 * 1000)))); + Assert.assertEquals("several hours ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (5 * 60 * 60 * 1000)))); + Assert.assertEquals("several days ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS)))); + Assert.assertEquals("several months ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 30)))); + Assert.assertEquals("several weeks ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (3 * DAY_IN_MILLIS * 7)))); + Assert.assertEquals("several years ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 365)))); + } + +} diff --git a/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timeago/version8/TimeAgoCalculatorUnitTest.java b/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timeago/version8/TimeAgoCalculatorUnitTest.java new file mode 100644 index 0000000000..0412b3c2fd --- /dev/null +++ b/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timeago/version8/TimeAgoCalculatorUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.timeago.version8; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; + +import org.junit.Assert; +import org.junit.Test; + +public class TimeAgoCalculatorUnitTest { + + @Test + public void calculateTimeAgoWithPeriodAndDurationTest() { + long DAY_IN_MILLIS = 1000 * 60 * 60 * 24; + Assert.assertEquals("moments ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()), ZoneId.systemDefault()), ZoneId.systemDefault())); + Assert.assertEquals("several seconds ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis() - (5 * 1000)), ZoneId.systemDefault()), ZoneId.systemDefault())); + Assert.assertEquals("several minutes ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis() - (5 * 60 * 1000)), ZoneId.systemDefault()), ZoneId.systemDefault())); + Assert.assertEquals("several hours ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis() - (5 * 60 * 60 * 1000)), ZoneId.systemDefault()), ZoneId.systemDefault())); + Assert.assertEquals("several days ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis() - (5 * DAY_IN_MILLIS)), ZoneId.systemDefault()), ZoneId.systemDefault())); + Assert.assertEquals("several months ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 30)), ZoneId.systemDefault()), ZoneId.systemDefault())); + Assert.assertEquals("several years ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 365)), ZoneId.systemDefault()), ZoneId.systemDefault())); + } +}