RelativeDateFormatter.java

  1. /*
  2.  * Copyright (C) 2011, Matthias Sohn <matthias.sohn@sap.com> and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */
  10. package org.eclipse.jgit.util;

  11. import java.text.MessageFormat;
  12. import java.util.Date;

  13. import org.eclipse.jgit.internal.JGitText;

  14. /**
  15.  * Formatter to format timestamps relative to the current time using time units
  16.  * in the format defined by {@code git log --relative-date}.
  17.  */
  18. public class RelativeDateFormatter {
  19.     static final long SECOND_IN_MILLIS = 1000;

  20.     static final long MINUTE_IN_MILLIS = 60 * SECOND_IN_MILLIS;

  21.     static final long HOUR_IN_MILLIS = 60 * MINUTE_IN_MILLIS;

  22.     static final long DAY_IN_MILLIS = 24 * HOUR_IN_MILLIS;

  23.     static final long WEEK_IN_MILLIS = 7 * DAY_IN_MILLIS;

  24.     static final long MONTH_IN_MILLIS = 30 * DAY_IN_MILLIS;

  25.     static final long YEAR_IN_MILLIS = 365 * DAY_IN_MILLIS;

  26.     /**
  27.      * Get age of given {@link java.util.Date} compared to now formatted in the
  28.      * same relative format as returned by {@code git log --relative-date}
  29.      *
  30.      * @param when
  31.      *            {@link java.util.Date} to format
  32.      * @return age of given {@link java.util.Date} compared to now formatted in
  33.      *         the same relative format as returned by
  34.      *         {@code git log --relative-date}
  35.      */
  36.     @SuppressWarnings("boxing")
  37.     public static String format(Date when) {

  38.         long ageMillis = SystemReader.getInstance().getCurrentTime()
  39.                 - when.getTime();

  40.         // shouldn't happen in a perfect world
  41.         if (ageMillis < 0)
  42.             return JGitText.get().inTheFuture;

  43.         // seconds
  44.         if (ageMillis < upperLimit(MINUTE_IN_MILLIS))
  45.             return MessageFormat.format(JGitText.get().secondsAgo,
  46.                     round(ageMillis, SECOND_IN_MILLIS));

  47.         // minutes
  48.         if (ageMillis < upperLimit(HOUR_IN_MILLIS))
  49.             return MessageFormat.format(JGitText.get().minutesAgo,
  50.                     round(ageMillis, MINUTE_IN_MILLIS));

  51.         // hours
  52.         if (ageMillis < upperLimit(DAY_IN_MILLIS))
  53.             return MessageFormat.format(JGitText.get().hoursAgo,
  54.                     round(ageMillis, HOUR_IN_MILLIS));

  55.         // up to 14 days use days
  56.         if (ageMillis < 14 * DAY_IN_MILLIS)
  57.             return MessageFormat.format(JGitText.get().daysAgo,
  58.                     round(ageMillis, DAY_IN_MILLIS));

  59.         // up to 10 weeks use weeks
  60.         if (ageMillis < 10 * WEEK_IN_MILLIS)
  61.             return MessageFormat.format(JGitText.get().weeksAgo,
  62.                     round(ageMillis, WEEK_IN_MILLIS));

  63.         // months
  64.         if (ageMillis < YEAR_IN_MILLIS)
  65.             return MessageFormat.format(JGitText.get().monthsAgo,
  66.                     round(ageMillis, MONTH_IN_MILLIS));

  67.         // up to 5 years use "year, months" rounded to months
  68.         if (ageMillis < 5 * YEAR_IN_MILLIS) {
  69.             long years = round(ageMillis, MONTH_IN_MILLIS) / 12;
  70.             String yearLabel = (years > 1) ? JGitText.get().years : //
  71.                     JGitText.get().year;
  72.             long months = round(ageMillis - years * YEAR_IN_MILLIS,
  73.                     MONTH_IN_MILLIS);
  74.             String monthLabel = (months > 1) ? JGitText.get().months : //
  75.                     (months == 1 ? JGitText.get().month : ""); //$NON-NLS-1$
  76.             return MessageFormat.format(
  77.                     months == 0 ? JGitText.get().years0MonthsAgo : JGitText
  78.                             .get().yearsMonthsAgo,
  79.                     new Object[] { years, yearLabel, months, monthLabel });
  80.         }

  81.         // years
  82.         return MessageFormat.format(JGitText.get().yearsAgo,
  83.                 round(ageMillis, YEAR_IN_MILLIS));
  84.     }

  85.     private static long upperLimit(long unit) {
  86.         long limit = unit + unit / 2;
  87.         return limit;
  88.     }

  89.     private static long round(long n, long unit) {
  90.         long rounded = (n + unit / 2) / unit;
  91.         return rounded;
  92.     }
  93. }