如何在Java中计算“time ago”?

时间:2020-12-04 01:28:37

In Ruby on Rails, there is a feature that allows you to take any Date and print out how "long ago" it was.

在Ruby on Rails中,有一个功能允许您使用任何日期并打印出“很久以前”的状态。

For example:

例如:

8 minutes ago
8 hours ago
8 days ago
8 months ago
8 years ago

Is there an easy way to do this in Java?

在Java中有一种简单的方法吗?

21 个解决方案

#1


152  

Take a look at the PrettyTime library.

看看PrettyTime库。

It's quite simple to use:

它使用起来非常简单:

import org.ocpsoft.prettytime.PrettyTime;

PrettyTime p = new PrettyTime();
System.out.println(p.format(new Date()));
// prints "moments ago"

You can also pass in a locale for internationalized messages:

您还可以传入国际化消息的区域设置:

PrettyTime p = new PrettyTime(new Locale("fr"));
System.out.println(p.format(new Date()));
// prints "à l'instant"

As noted in the comments, Android has this functionality built into the android.text.format.DateUtils class.

如评论中所述,Android具有内置于android.text.format.DateUtils类中的此功能。

#2


65  

Have you considered the TimeUnit enum? It can be pretty useful for this kind of thing

你考虑过TimeUnit枚举吗?它对于这种事情非常有用

    try {
        SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
        Date past = format.parse("01/10/2010");
        Date now = new Date();

        System.out.println(TimeUnit.MILLISECONDS.toMillis(now.getTime() - past.getTime()) + " milliseconds ago");
        System.out.println(TimeUnit.MILLISECONDS.toMinutes(now.getTime() - past.getTime()) + " minutes ago");
        System.out.println(TimeUnit.MILLISECONDS.toHours(now.getTime() - past.getTime()) + " hours ago");
        System.out.println(TimeUnit.MILLISECONDS.toDays(now.getTime() - past.getTime()) + " days ago");
    }
    catch (Exception j){
        j.printStackTrace();
    }

#3


41  

  public class TimeUtils {

      public final static long ONE_SECOND = 1000;
      public final static long SECONDS = 60;

      public final static long ONE_MINUTE = ONE_SECOND * 60;
      public final static long MINUTES = 60;

      public final static long ONE_HOUR = ONE_MINUTE * 60;
      public final static long HOURS = 24;

      public final static long ONE_DAY = ONE_HOUR * 24;

      private TimeUtils() {
      }

      /**
       * converts time (in milliseconds) to human-readable format
       *  "<w> days, <x> hours, <y> minutes and (z) seconds"
       */
      public static String millisToLongDHMS(long duration) {
        StringBuffer res = new StringBuffer();
        long temp = 0;
        if (duration >= ONE_SECOND) {
          temp = duration / ONE_DAY;
          if (temp > 0) {
            duration -= temp * ONE_DAY;
            res.append(temp).append(" day").append(temp > 1 ? "s" : "")
               .append(duration >= ONE_MINUTE ? ", " : "");
          }

          temp = duration / ONE_HOUR;
          if (temp > 0) {
            duration -= temp * ONE_HOUR;
            res.append(temp).append(" hour").append(temp > 1 ? "s" : "")
               .append(duration >= ONE_MINUTE ? ", " : "");
          }

          temp = duration / ONE_MINUTE;
          if (temp > 0) {
            duration -= temp * ONE_MINUTE;
            res.append(temp).append(" minute").append(temp > 1 ? "s" : "");
          }

          if (!res.toString().equals("") && duration >= ONE_SECOND) {
            res.append(" and ");
          }

          temp = duration / ONE_SECOND;
          if (temp > 0) {
            res.append(temp).append(" second").append(temp > 1 ? "s" : "");
          }
          return res.toString();
        } else {
          return "0 second";
        }
      }


      public static void main(String args[]) {
        System.out.println(millisToLongDHMS(123));
        System.out.println(millisToLongDHMS((5 * ONE_SECOND) + 123));
        System.out.println(millisToLongDHMS(ONE_DAY + ONE_HOUR));
        System.out.println(millisToLongDHMS(ONE_DAY + 2 * ONE_SECOND));
        System.out.println(millisToLongDHMS(ONE_DAY + ONE_HOUR + (2 * ONE_MINUTE)));
        System.out.println(millisToLongDHMS((4 * ONE_DAY) + (3 * ONE_HOUR)
            + (2 * ONE_MINUTE) + ONE_SECOND));
        System.out.println(millisToLongDHMS((5 * ONE_DAY) + (4 * ONE_HOUR)
            + ONE_MINUTE + (23 * ONE_SECOND) + 123));
        System.out.println(millisToLongDHMS(42 * ONE_DAY));
        /*
          output :
                0 second
                5 seconds
                1 day, 1 hour
                1 day and 2 seconds
                1 day, 1 hour, 2 minutes
                4 days, 3 hours, 2 minutes and 1 second
                5 days, 4 hours, 1 minute and 23 seconds
                42 days
         */
    }
}

more @Format a duration in milliseconds into a human-readable format

更多@Format以毫秒为单位的持续时间,形成人类可读的格式

#4


33  

I take RealHowTo and Ben J answers and make my own version:

我采用RealHowTo和Ben J的答案并制作我自己的版本:

public class TimeAgo {
public static final List<Long> times = Arrays.asList(
        TimeUnit.DAYS.toMillis(365),
        TimeUnit.DAYS.toMillis(30),
        TimeUnit.DAYS.toMillis(1),
        TimeUnit.HOURS.toMillis(1),
        TimeUnit.MINUTES.toMillis(1),
        TimeUnit.SECONDS.toMillis(1) );
public static final List<String> timesString = Arrays.asList("year","month","day","hour","minute","second");

public static String toDuration(long duration) {

    StringBuffer res = new StringBuffer();
    for(int i=0;i< TimeAgo.times.size(); i++) {
        Long current = TimeAgo.times.get(i);
        long temp = duration/current;
        if(temp>0) {
            res.append(temp).append(" ").append( TimeAgo.timesString.get(i) ).append(temp != 1 ? "s" : "").append(" ago");
            break;
        }
    }
    if("".equals(res.toString()))
        return "0 seconds ago";
    else
        return res.toString();
}
public static void main(String args[]) {
    System.out.println(toDuration(123));
    System.out.println(toDuration(1230));
    System.out.println(toDuration(12300));
    System.out.println(toDuration(123000));
    System.out.println(toDuration(1230000));
    System.out.println(toDuration(12300000));
    System.out.println(toDuration(123000000));
    System.out.println(toDuration(1230000000));
    System.out.println(toDuration(12300000000L));
    System.out.println(toDuration(123000000000L));
}}

which will print the following

这将打印以下内容

0 second ago
1 second ago
12 seconds ago
2 minutes ago
20 minutes ago
3 hours ago
1 day ago
14 days ago
4 months ago
3 years ago

#5


9  

This is based on RealHowTo's answer so if you like it, give him/her some love too.

这是基于RealHowTo的答案,所以如果你喜欢它,也要给他/她一些爱。

This cleaned up version allows you to specify the range of time you might be interested in.

此清理版本允许您指定您可能感兴趣的时间范围。

It also handles the " and " part a little differently. I often find when joining strings with a delimiter it's ofter easier to skip the complicated logic and just delete the last delimiter when you're done.

它还处理“和”部分有点不同。我经常发现,当使用分隔符连接字符串时,更容易跳过复杂的逻辑,并在完成后删除最后一个分隔符。

import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.MILLISECONDS;

public class TimeUtils {

    /**
     * Converts time to a human readable format within the specified range
     *
     * @param duration the time in milliseconds to be converted
     * @param max      the highest time unit of interest
     * @param min      the lowest time unit of interest
     */
    public static String formatMillis(long duration, TimeUnit max, TimeUnit min) {
        StringBuilder res = new StringBuilder();

        TimeUnit current = max;

        while (duration > 0) {
            long temp = current.convert(duration, MILLISECONDS);

            if (temp > 0) {
                duration -= current.toMillis(temp);
                res.append(temp).append(" ").append(current.name().toLowerCase());
                if (temp < 2) res.deleteCharAt(res.length() - 1);
                res.append(", ");
            }

            if (current == min) break;

            current = TimeUnit.values()[current.ordinal() - 1];
        }

        // clean up our formatting....

        // we never got a hit, the time is lower than we care about
        if (res.lastIndexOf(", ") < 0) return "0 " + min.name().toLowerCase();

        // yank trailing  ", "
        res.deleteCharAt(res.length() - 2);

        //  convert last ", " to " and"
        int i = res.lastIndexOf(", ");
        if (i > 0) {
            res.deleteCharAt(i);
            res.insert(i, " and");
        }

        return res.toString();
    }
}

Little code to give it a whirl:

很少的代码让它旋转:

import static java.util.concurrent.TimeUnit.*;

public class Main {

    public static void main(String args[]) {
        long[] durations = new long[]{
            123,
            SECONDS.toMillis(5) + 123,
            DAYS.toMillis(1) + HOURS.toMillis(1),
            DAYS.toMillis(1) + SECONDS.toMillis(2),
            DAYS.toMillis(1) + HOURS.toMillis(1) + MINUTES.toMillis(2),
            DAYS.toMillis(4) + HOURS.toMillis(3) + MINUTES.toMillis(2) + SECONDS.toMillis(1),
            DAYS.toMillis(5) + HOURS.toMillis(4) + MINUTES.toMillis(1) + SECONDS.toMillis(23) + 123,
            DAYS.toMillis(42)
        };

        for (long duration : durations) {
            System.out.println(TimeUtils.formatMillis(duration, DAYS, SECONDS));
        }

        System.out.println("\nAgain in only hours and minutes\n");

        for (long duration : durations) {
            System.out.println(TimeUtils.formatMillis(duration, HOURS, MINUTES));
        }
    }

}

Which will output the following:

这将输出以下内容:

0 seconds
5 seconds 
1 day and 1 hour 
1 day and 2 seconds 
1 day, 1 hour and 2 minutes 
4 days, 3 hours, 2 minutes and 1 second 
5 days, 4 hours, 1 minute and 23 seconds 
42 days 

Again in only hours and minutes

0 minutes
0 minutes
25 hours 
24 hours 
25 hours and 2 minutes 
99 hours and 2 minutes 
124 hours and 1 minute 
1008 hours 

And in case anyone ever needs it, here's a class that will convert any string like the above back into milliseconds. It's pretty useful for allowing people to specify timeouts of various things in readable text.

如果有人需要它,这里有一个类将上面的任何字符串转换回毫秒。它对于允许人们在可读文本中指定各种事物的超时非常有用。

#6


8  

there's a simple way to do this:

这有一个简单的方法:

let's say you want the time 20 minutes ago:

假设你想要20分钟前的时间:

Long minutesAgo = new Long(20);
Date date = new Date();
Date dateIn_X_MinAgo = new Date (date.getTime() - minutesAgo*60*1000);

that's it..

而已..

#7


6  

java.time

Using the java.time framework built into Java 8 and later.

使用Java 8及更高版本中内置的java.time框架。

LocalDateTime t1 = LocalDateTime.of(2015, 1, 1, 0, 0, 0);
LocalDateTime t2 = LocalDateTime.now();
Period period = Period.between(t1.toLocalDate(), t2.toLocalDate());
Duration duration = Duration.between(t1, t2);

System.out.println("First January 2015 is " + period.getYears() + " years ago");
System.out.println("First January 2015 is " + period.getMonths() + " months ago");
System.out.println("First January 2015 is " + period.getDays() + " days ago");
System.out.println("First January 2015 is " + duration.toHours() + " hours ago");
System.out.println("First January 2015 is " + duration.toMinutes() + " minutes ago");

#8


5  

If you looking for a simple "Today", "Yesterday" or "x days ago".

如果你想找一个简单的“今天”,“昨天”或“x天前”。

private String getDaysAgo(Date date){
    long days = (new Date().getTime() - date.getTime()) / 86400000;

    if(days == 0) return "Today";
    else if(days == 1) return "Yesterday";
    else return days + " days ago";
}

#9


5  

About built-in solutions:

关于内置解决方案:

Java does not have any built-in support for formatting relative times, also not Java-8 and its new package java.time. If you only need English and nothing else then and only then a hand-made solution might be acceptable - see the answer of @RealHowTo (although it has the strong disadvantage to not take into account the timezone for the translation of instant deltas to local time units!). Anyway, if you want to avoid home-grown complex workarounds especially for other locales then you need an external library.

Java没有任何内置的格式化相对时间的支持,也没有Java-8及其新的包java.time。如果你只需要英语而不需要其他任何东西,那么只有手工制作的解决方案才可以接受 - 请参阅@RealHowTo的答案(虽然它有一个很大的缺点,就是不考虑将即时增量转换为当地时间的时区单位!)。无论如何,如果你想避免本土复杂的解决方法,特别是对于其他语言环境,那么你需要一个外部库。

In latter case, I recommend to use my library Time4J (or Time4A on Android). It offers greatest flexibility and most i18n-power. The class net.time4j.PrettyTime has seven methods printRelativeTime...(...) for this purpose. Example using a test clock as time source:

在后一种情况下,我建议使用我的库Time4J(或Android上的Time4A)。它提供了最大的灵活性和大多数i18n功率。 net.time4j.PrettyTime类为此目的有七个方法printRelativeTime ...(...)。使用测试时钟作为时间源的示例:

TimeSource<?> clock = () -> PlainTimestamp.of(2015, 8, 1, 10, 24, 5).atUTC();
Moment moment = PlainTimestamp.of(2015, 8, 1, 17, 0).atUTC(); // our input
String durationInDays =
  PrettyTime.of(Locale.GERMAN).withReferenceClock(clock).printRelative(
    moment,
    Timezone.of(EUROPE.BERLIN),
    TimeUnit.DAYS); // controlling the precision
System.out.println(durationInDays); // heute (german word for today)

Another example using java.time.Instant as input:

使用java.time.Instant作为输入的另一个示例:

String relativeTime = 
  PrettyTime.of(Locale.ENGLISH)
    .printRelativeInStdTimezone(Moment.from(Instant.EPOCH));
System.out.println(relativeTime); // 45 years ago

This library supports via its latest version (v4.17) 80 languages and also some country-specific locales (especially for Spanish, English, Arabic, French). The i18n-data are mainly based on the newest CLDR-version v29. Other important reasons why to use this library are good support for plural rules (which are often different from English in other locales), abbreviated format style (for example: "1 sec ago") and expressive ways for taking into account timezones. Time4J is even aware of such exotic details like leap seconds in calculations of relative times (not really important but it forms a message related to the expectation horizon). The compatibility with Java-8 exists due to easily available conversion methods for types like java.time.Instant or java.time.Period.

该库通过其最新版本(v4.17)支持80种语言以及一些特定国家/地区的语言环境(特别是西班牙语,英语,阿拉伯语,法语)。 i18n数据主要基于最新的CLDR版本v29。使用此库的其他重要原因是对多个规则(通常与其他语言环境中的英语不同),缩写格式样式(例如:“1秒前”)以及考虑时区的表达方式的良好支持。 Time4J甚至意识到这些奇特的细节,比如计算相对时间的闰秒(不是很重要,但它形成了与期望视野相关的信息)。由于java.time.Instant或java.time.Period等类型的易于使用的转换方法,因此与Java-8的兼容性存在。

Are there any drawbacks? Only two.

有什么缺点吗?只有两个。

  • The library is not small (also because of its big i18n-data repository).
  • 该库不小(也因为其庞大的i18n数据存储库)。
  • The API is not well known so community knowledge and support are not available yet otherwise the supplied documentation is pretty detailed and comprehensive.
  • API并不为人所知,因此社区知识和支持尚不可用,否则所提供的文档非常详细和全面。

(Compact) alternatives:

(紧凑型)替代品:

If you look for a smaller solution and don't need so many features and are willing to tolerate possible quality issues related to i18n-data then:

如果您寻找更小的解决方案,并且不需要这么多功能,并且愿意容忍与i18n-data相关的可能的质量问题,那么:

  • I would recommend ocpsoft/PrettyTime (support for actually 32 languages (soon 34?) suitable for work with java.util.Date only - see the answer of @ataylor). The industry standard CLDR (from Unicode consortium) with its big community background is unfortunatly not a base of the i18n-data so further enhancements or improvements of data can take a while...

    我建议ocpsoft / PrettyTime(实际支持32种语言(很快34?)只适合与java.util.Date一起工作 - 请参阅@ataylor的答案)。具有巨大社区背景的行业标准CLDR(来自Unicode联盟)不幸地不是i18n数据的基础,因此数据的进一步增强或改进可能需要一段时间......

  • If you are on Android then the helper class android.text.format.DateUtils is a slim built-in alternative (see other comments and answers here, with the disadvantage that it has no support for years and months. And I am sure that only very few people like the API-style of this helper class.

    如果你在Android上,那么辅助类android.text.format.DateUtils是一个纤薄的内置替代品(请参阅其他评论和答案,缺点是它几年和几个月都没有支持。而且我确信只有很少有人喜欢这个助手类的API风格。

  • If you are a fan of Joda-Time then you can look at its class PeriodFormat (support for 14 languages in release v2.9.4, on the other side: Joda-Time is surely not compact, too, so I mention it here just for completeness). This library is not a real answer because relative times are not supported at all. You will need to append the literal " ago" at least (and manually stripping off all lower units from generated list formats - awkward). Unlike Time4J or Android-DateUtils, it has no special support for abbreviations or automatic switching from relative times to absolute time representations. Like PrettyTime, it is totally dependent on the unconfirmed contributions of private members of the Java-community to its i18n-data.

    如果您是Joda-Time的粉丝,那么您可以查看它的类PeriodFormat(在版本v2.9.4中支持14种语言,另一方面:Joda-Time肯定也不紧凑,所以我在这里提到它只是为了完整性)。这个库不是真正的答案,因为根本不支持相对时间。您至少需要附加文字“之前”(并从生成的列表格式中手动剥离所有较低的单位 - 笨拙)。与Time4J或Android-DateUtils不同,它没有特别支持缩写或从相对时间到绝对时间表示的自动切换。与PrettyTime一样,它完全依赖于Java社区的私有成员对其i18n数据的未经证实的贡献。

#10


4  

I created a simple Java timeago port of the jquery-timeago plug-in that does what you are asking for.

我创建了一个jquery-timeago插件的简单Java timeago端口,可以满足您的需求。

TimeAgo time = new TimeAgo();
String minutes = time.timeAgo(System.currentTimeMillis() - (15*60*1000)); // returns "15 minutes ago"

#11


3  

The joda-time package, has the notion of Periods. You can do arithmetic with Periods and DateTimes.

joda-time包,有Periods的概念。您可以使用Periods和DateTimes进行算术运算。

From the docs:

来自文档:

public boolean isRentalOverdue(DateTime datetimeRented) {
  Period rentalPeriod = new  Period().withDays(2).withHours(12);
  return datetimeRented.plus(rentalPeriod).isBeforeNow();
}

#12


3  

You Can use this function to calculate time ago

您可以使用此功能计算时间

 private String timeAgo(long time_ago) {
        long cur_time = (Calendar.getInstance().getTimeInMillis()) / 1000;
        long time_elapsed = cur_time - time_ago;
        long seconds = time_elapsed;
        int minutes = Math.round(time_elapsed / 60);
        int hours = Math.round(time_elapsed / 3600);
        int days = Math.round(time_elapsed / 86400);
        int weeks = Math.round(time_elapsed / 604800);
        int months = Math.round(time_elapsed / 2600640);
        int years = Math.round(time_elapsed / 31207680);

        // Seconds
        if (seconds <= 60) {
            return "just now";
        }
        //Minutes
        else if (minutes <= 60) {
            if (minutes == 1) {
                return "one minute ago";
            } else {
                return minutes + " minutes ago";
            }
        }
        //Hours
        else if (hours <= 24) {
            if (hours == 1) {
                return "an hour ago";
            } else {
                return hours + " hrs ago";
            }
        }
        //Days
        else if (days <= 7) {
            if (days == 1) {
                return "yesterday";
            } else {
                return days + " days ago";
            }
        }
        //Weeks
        else if (weeks <= 4.3) {
            if (weeks == 1) {
                return "a week ago";
            } else {
                return weeks + " weeks ago";
            }
        }
        //Months
        else if (months <= 12) {
            if (months == 1) {
                return "a month ago";
            } else {
                return months + " months ago";
            }
        }
        //Years
        else {
            if (years == 1) {
                return "one year ago";
            } else {
                return years + " years ago";
            }
        }
    }

1) Here time_ago is in microsecond

1)这里time_ago是微秒

#13


2  

It's not pretty...but the closest I can think of is using Joda-Time (as described in this post: How to calculate elapsed time from now with Joda Time?

它并不漂亮...但我能想到的最接近的是使用Joda-Time(如本文所述:如何用Joda Time计算从现在开始的经过时间?

#14


2  

In case you're developing an app for Android, it provides the utility class DateUtils for all such requirements. Take a look at the DateUtils#getRelativeTimeSpanString() utility method.

如果您正在为Android开发应用程序,它会为所有此类要求提供实用程序类DateUtils。看一下DateUtils#getRelativeTimeSpanString()实用程序方法。

From the docs for

来自文档

CharSequence getRelativeTimeSpanString (long time, long now, long minResolution)

CharSequence getRelativeTimeSpanString(很长一段时间,很长一段时间,很长的minResolution)

Returns a string describing 'time' as a time relative to 'now'. Time spans in the past are formatted like "42 minutes ago". Time spans in the future are formatted like "In 42 minutes".

返回一个字符串,描述'time'作为相对于'now'的时间。过去的时间跨度格式为“42分钟前”。未来的时间跨度格式为“在42分钟内”。

You'll be passing your timestamp as time and System.currentTimeMillis() as now. The minResolution lets you specify the minimum timespan to report.

你将把时间戳作为时间和System.currentTimeMillis()传递给你。 minResolution允许您指定要报告的最小时间跨度。

For example, a time 3 seconds in the past will be reported as "0 minutes ago" if this is set to MINUTE_IN_MILLIS. Pass one of 0, MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS, WEEK_IN_MILLIS etc.

例如,如果设置为MINUTE_IN_MILLIS,则过去3秒的时间将报告为“0分钟前”。传递0,MINUTE_IN_MILLIS,HOUR_IN_MILLIS,DAY_IN_MILLIS,WEEK_IN_MILLIS等中的一个。

#15


2  

This is a better code if we consider performance.It reduces the number of calculations. Reason Minutes are calculated only if the number of seconds is greater than 60 and Hours are calculated only if the number of minutes is greater than 60 and so on...

如果我们考虑性能,这是一个更好的代码。它减少了计算次数。仅当秒数大于60时计算原因分钟,并且仅在分钟数大于60时计算小时数等等...

class timeAgo {

static String getTimeAgo(long time_ago) {
    time_ago=time_ago/1000;
    long cur_time = (Calendar.getInstance().getTimeInMillis())/1000 ;
    long time_elapsed = cur_time - time_ago;
    long seconds = time_elapsed;
   // Seconds
    if (seconds <= 60) {
        return "Just now";
    }
    //Minutes
    else{
        int minutes = Math.round(time_elapsed / 60);

        if (minutes <= 60) {
            if (minutes == 1) {
                return "a minute ago";
            } else {
                return minutes + " minutes ago";
            }
        }
        //Hours
        else {
            int hours = Math.round(time_elapsed / 3600);
            if (hours <= 24) {
                if (hours == 1) {
                    return "An hour ago";
                } else {
                    return hours + " hrs ago";
                }
            }
            //Days
            else {
                int days = Math.round(time_elapsed / 86400);
                if (days <= 7) {
                    if (days == 1) {
                        return "Yesterday";
                    } else {
                        return days + " days ago";
                    }
                }
                //Weeks
                else {
                    int weeks = Math.round(time_elapsed / 604800);
                    if (weeks <= 4.3) {
                        if (weeks == 1) {
                            return "A week ago";
                        } else {
                            return weeks + " weeks ago";
                        }
                    }
                    //Months
                    else {
                        int months = Math.round(time_elapsed / 2600640);
                        if (months <= 12) {
                            if (months == 1) {
                                return "A month ago";
                            } else {
                                return months + " months ago";
                            }
                        }
                        //Years
                        else {
                            int years = Math.round(time_elapsed / 31207680);
                            if (years == 1) {
                                return "One year ago";
                            } else {
                                return years + " years ago";
                            }
                        }
                    }
                }
            }
        }
    }

}

}

#16


1  

After long research i found this.

经过长时间的研究我发现了这个

    public class GetTimeLapse {
    public static String getlongtoago(long createdAt) {
        DateFormat userDateFormat = new SimpleDateFormat("E MMM dd HH:mm:ss Z yyyy");
        DateFormat dateFormatNeeded = new SimpleDateFormat("MM/dd/yyyy HH:MM:SS");
        Date date = null;
        date = new Date(createdAt);
        String crdate1 = dateFormatNeeded.format(date);

        // Date Calculation
        DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
        crdate1 = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(date);

        // get current date time with Calendar()
        Calendar cal = Calendar.getInstance();
        String currenttime = dateFormat.format(cal.getTime());

        Date CreatedAt = null;
        Date current = null;
        try {
            CreatedAt = dateFormat.parse(crdate1);
            current = dateFormat.parse(currenttime);
        } catch (java.text.ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // Get msec from each, and subtract.
        long diff = current.getTime() - CreatedAt.getTime();
        long diffSeconds = diff / 1000;
        long diffMinutes = diff / (60 * 1000) % 60;
        long diffHours = diff / (60 * 60 * 1000) % 24;
        long diffDays = diff / (24 * 60 * 60 * 1000);

        String time = null;
        if (diffDays > 0) {
            if (diffDays == 1) {
                time = diffDays + "day ago ";
            } else {
                time = diffDays + "days ago ";
            }
        } else {
            if (diffHours > 0) {
                if (diffHours == 1) {
                    time = diffHours + "hr ago";
                } else {
                    time = diffHours + "hrs ago";
                }
            } else {
                if (diffMinutes > 0) {
                    if (diffMinutes == 1) {
                        time = diffMinutes + "min ago";
                    } else {
                        time = diffMinutes + "mins ago";
                    }
                } else {
                    if (diffSeconds > 0) {
                        time = diffSeconds + "secs ago";
                    }
                }

            }

        }
        return time;
    }
}

#17


1  

For Android Exactly like Ravi said, but since lots of people want to just copy paste the thing here it is.

对于Android完全像Ravi所说的那样,但由于很多人只想复制粘贴这里的东西。

  try {
      SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
      Date dt = formatter.parse(date_from_server);
      CharSequence output = DateUtils.getRelativeTimeSpanString (dt.getTime());
      your_textview.setText(output.toString());
    } catch (Exception ex) {
      ex.printStackTrace();
      your_textview.setText("");
    }

Explanation for people that have more time

对有更多时间的人的解释

  1. You get the data from somewhere. First you have to figure out it's format.
  2. 你从某个地方获得数据。首先,你必须弄清楚它的格式。

Ex. I get the data from a server in the format Wed, 27 Jan 2016 09:32:35 GMT [this is probably NOT your case]

防爆。我从格林威治标准时间2016年1月27日09:32:35格式的服务器获取数据[这可能不是你的情况]

this is translated into

这被翻译成

SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");

SimpleDateFormat formatter = new SimpleDateFormat(“EEE,dd MMM yyyy HH:mm:ss Z”);

how do I know it? Read the documentation here.

我怎么知道的?阅读此处的文档。

Then after I parse it I get a date. that date I put in the getRelativeTimeSpanString (without any additional parameters is fine by me, to be default to minutes)

然后我解析它后得到一个约会。那个日期我放入了getRelativeTimeSpanString(没有任何额外的参数对我来说很好,默认为几分钟)

You WILL get an exception if you didn't figure out the correct parsing String, Something like: exception at character 5. Look at character 5, and correct your initial parsing string.. You might get another exception, repeat this steps until you have the correct formula.

如果你没有找到正确的解析字符串,你会得到一个异常,例如:字符5处的异常。查看字符5,并更正你的初始解析字符串..你可能会得到另一个异常,重复这些步骤直到你有正确的公式。

#18


1  

Based on a bunch of answers here, I created the following for my use case.

基于这里的一堆答案,我为我的用例创建了以下内容。

Example usage:

用法示例:

String relativeDate = String.valueOf(
                TimeUtils.getRelativeTime( 1000L * myTimeInMillis() ));

import java.util.Arrays;
import java.util.List;

import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;

/**
 * Utilities for dealing with dates and times
 */
public class TimeUtils {

    public static final List<Long> times = Arrays.asList(
        DAYS.toMillis(365),
        DAYS.toMillis(30),
        DAYS.toMillis(7),
        DAYS.toMillis(1),
        HOURS.toMillis(1),
        MINUTES.toMillis(1),
        SECONDS.toMillis(1)
    );

    public static final List<String> timesString = Arrays.asList(
        "yr", "mo", "wk", "day", "hr", "min", "sec"
    );

    /**
     * Get relative time ago for date
     *
     * NOTE:
     *  if (duration > WEEK_IN_MILLIS) getRelativeTimeSpanString prints the date.
     *
     * ALT:
     *  return getRelativeTimeSpanString(date, now, SECOND_IN_MILLIS, FORMAT_ABBREV_RELATIVE);
     *
     * @param date String.valueOf(TimeUtils.getRelativeTime(1000L * Date/Time in Millis)
     * @return relative time
     */
    public static CharSequence getRelativeTime(final long date) {
        return toDuration( Math.abs(System.currentTimeMillis() - date) );
    }

    private static String toDuration(long duration) {
        StringBuilder sb = new StringBuilder();
        for(int i=0;i< times.size(); i++) {
            Long current = times.get(i);
            long temp = duration / current;
            if (temp > 0) {
                sb.append(temp)
                  .append(" ")
                  .append(timesString.get(i))
                  .append(temp > 1 ? "s" : "")
                  .append(" ago");
                break;
            }
        }
        return sb.toString().isEmpty() ? "now" : sb.toString();
    }
}

#19


0  

Here is my Java Implementation of this

这是我的Java实现

    public static String relativeDate(Date date){
    Date now=new Date();
    if(date.before(now)){
    int days_passed=(int) TimeUnit.MILLISECONDS.toDays(now.getTime() - date.getTime());
    if(days_passed>1)return days_passed+" days ago";
    else{
        int hours_passed=(int) TimeUnit.MILLISECONDS.toHours(now.getTime() - date.getTime());
        if(hours_passed>1)return days_passed+" hours ago";
        else{
            int minutes_passed=(int) TimeUnit.MILLISECONDS.toMinutes(now.getTime() - date.getTime());
            if(minutes_passed>1)return minutes_passed+" minutes ago";
            else{
                int seconds_passed=(int) TimeUnit.MILLISECONDS.toSeconds(now.getTime() - date.getTime());
                return seconds_passed +" seconds ago";
            }
        }
    }

    }
    else
    {
        return new SimpleDateFormat("HH:mm:ss MM/dd/yyyy").format(date).toString();
    }
  }

#20


0  

it works for me

这个对我有用

public class TimeDifference {
    int years;
    int months;
    int days;
    int hours;
    int minutes;
    int seconds;
    String differenceString;

    public TimeDifference(@NonNull Date curdate, @NonNull Date olddate) {

        float diff = curdate.getTime() - olddate.getTime();
        if (diff >= 0) {
            int yearDiff = Math.round((diff / (AppConstant.aLong * AppConstant.aFloat)) >= 1 ? (diff / (AppConstant.aLong * AppConstant.aFloat)) : 0);
            if (yearDiff > 0) {
                years = yearDiff;
                setDifferenceString(years + (years == 1 ? " year" : " years") + " ago");
            } else {
                int monthDiff = Math.round((diff / AppConstant.aFloat) >= 1 ? (diff / AppConstant.aFloat) : 0);
                if (monthDiff > 0) {
                    if (monthDiff > AppConstant.ELEVEN) {
                        monthDiff = AppConstant.ELEVEN;
                    }
                    months = monthDiff;
                    setDifferenceString(months + (months == 1 ? " month" : " months") + " ago");
                } else {
                    int dayDiff = Math.round((diff / (AppConstant.bFloat)) >= 1 ? (diff / (AppConstant.bFloat)) : 0);
                    if (dayDiff > 0) {
                        days = dayDiff;
                        if (days == AppConstant.THIRTY) {
                            days = AppConstant.TWENTYNINE;
                        }
                        setDifferenceString(days + (days == 1 ? " day" : " days") + " ago");
                    } else {
                        int hourDiff = Math.round((diff / (AppConstant.cFloat)) >= 1 ? (diff / (AppConstant.cFloat)) : 0);
                        if (hourDiff > 0) {
                            hours = hourDiff;
                            setDifferenceString(hours + (hours == 1 ? " hour" : " hours") + " ago");
                        } else {
                            int minuteDiff = Math.round((diff / (AppConstant.dFloat)) >= 1 ? (diff / (AppConstant.dFloat)) : 0);
                            if (minuteDiff > 0) {
                                minutes = minuteDiff;
                                setDifferenceString(minutes + (minutes == 1 ? " minute" : " minutes") + " ago");
                            } else {
                                int secondDiff = Math.round((diff / (AppConstant.eFloat)) >= 1 ? (diff / (AppConstant.eFloat)) : 0);
                                if (secondDiff > 0) {
                                    seconds = secondDiff;
                                } else {
                                    seconds = 1;
                                }
                                setDifferenceString(seconds + (seconds == 1 ? " second" : " seconds") + " ago");
                            }
                        }
                    }

                }
            }

        } else {
            setDifferenceString("Just now");
        }

    }

    public String getDifferenceString() {
        return differenceString;
    }

    public void setDifferenceString(String differenceString) {
        this.differenceString = differenceString;
    }

    public int getYears() {
        return years;
    }

    public void setYears(int years) {
        this.years = years;
    }

    public int getMonths() {
        return months;
    }

    public void setMonths(int months) {
        this.months = months;
    }

    public int getDays() {
        return days;
    }

    public void setDays(int days) {
        this.days = days;
    }

    public int getHours() {
        return hours;
    }

    public void setHours(int hours) {
        this.hours = hours;
    }

    public int getMinutes() {
        return minutes;
    }

    public void setMinutes(int minutes) {
        this.minutes = minutes;
    }

    public int getSeconds() {
        return seconds;
    }

    public void setSeconds(int seconds) {
        this.seconds = seconds;
    } }

#21


0  

This is the very basic script. its easy to improvized.
Result : (XXX Hours Ago), or (XX Days Ago/Yesterday/Today)

这是非常基本的脚本。它易于改进。结果:(XXX小时前),或(XX天前/昨天/今天)

<span id='hourpost'></span>
,or
<span id='daypost'></span>

<script>
var postTime = new Date('2017/6/9 00:01'); 
var now = new Date();
var difference = now.getTime() - postTime.getTime();
var minutes = Math.round(difference/60000);
var hours = Math.round(minutes/60);
var days = Math.round(hours/24);

var result;
if (days < 1) {
result = "Today";
} else if (days < 2) {
result = "Yesterday";
} else {
result = days + " Days ago";
}

document.getElementById("hourpost").innerHTML = hours + "Hours Ago" ;
document.getElementById("daypost").innerHTML = result ;
</script>

#1


152  

Take a look at the PrettyTime library.

看看PrettyTime库。

It's quite simple to use:

它使用起来非常简单:

import org.ocpsoft.prettytime.PrettyTime;

PrettyTime p = new PrettyTime();
System.out.println(p.format(new Date()));
// prints "moments ago"

You can also pass in a locale for internationalized messages:

您还可以传入国际化消息的区域设置:

PrettyTime p = new PrettyTime(new Locale("fr"));
System.out.println(p.format(new Date()));
// prints "à l'instant"

As noted in the comments, Android has this functionality built into the android.text.format.DateUtils class.

如评论中所述,Android具有内置于android.text.format.DateUtils类中的此功能。

#2


65  

Have you considered the TimeUnit enum? It can be pretty useful for this kind of thing

你考虑过TimeUnit枚举吗?它对于这种事情非常有用

    try {
        SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
        Date past = format.parse("01/10/2010");
        Date now = new Date();

        System.out.println(TimeUnit.MILLISECONDS.toMillis(now.getTime() - past.getTime()) + " milliseconds ago");
        System.out.println(TimeUnit.MILLISECONDS.toMinutes(now.getTime() - past.getTime()) + " minutes ago");
        System.out.println(TimeUnit.MILLISECONDS.toHours(now.getTime() - past.getTime()) + " hours ago");
        System.out.println(TimeUnit.MILLISECONDS.toDays(now.getTime() - past.getTime()) + " days ago");
    }
    catch (Exception j){
        j.printStackTrace();
    }

#3


41  

  public class TimeUtils {

      public final static long ONE_SECOND = 1000;
      public final static long SECONDS = 60;

      public final static long ONE_MINUTE = ONE_SECOND * 60;
      public final static long MINUTES = 60;

      public final static long ONE_HOUR = ONE_MINUTE * 60;
      public final static long HOURS = 24;

      public final static long ONE_DAY = ONE_HOUR * 24;

      private TimeUtils() {
      }

      /**
       * converts time (in milliseconds) to human-readable format
       *  "<w> days, <x> hours, <y> minutes and (z) seconds"
       */
      public static String millisToLongDHMS(long duration) {
        StringBuffer res = new StringBuffer();
        long temp = 0;
        if (duration >= ONE_SECOND) {
          temp = duration / ONE_DAY;
          if (temp > 0) {
            duration -= temp * ONE_DAY;
            res.append(temp).append(" day").append(temp > 1 ? "s" : "")
               .append(duration >= ONE_MINUTE ? ", " : "");
          }

          temp = duration / ONE_HOUR;
          if (temp > 0) {
            duration -= temp * ONE_HOUR;
            res.append(temp).append(" hour").append(temp > 1 ? "s" : "")
               .append(duration >= ONE_MINUTE ? ", " : "");
          }

          temp = duration / ONE_MINUTE;
          if (temp > 0) {
            duration -= temp * ONE_MINUTE;
            res.append(temp).append(" minute").append(temp > 1 ? "s" : "");
          }

          if (!res.toString().equals("") && duration >= ONE_SECOND) {
            res.append(" and ");
          }

          temp = duration / ONE_SECOND;
          if (temp > 0) {
            res.append(temp).append(" second").append(temp > 1 ? "s" : "");
          }
          return res.toString();
        } else {
          return "0 second";
        }
      }


      public static void main(String args[]) {
        System.out.println(millisToLongDHMS(123));
        System.out.println(millisToLongDHMS((5 * ONE_SECOND) + 123));
        System.out.println(millisToLongDHMS(ONE_DAY + ONE_HOUR));
        System.out.println(millisToLongDHMS(ONE_DAY + 2 * ONE_SECOND));
        System.out.println(millisToLongDHMS(ONE_DAY + ONE_HOUR + (2 * ONE_MINUTE)));
        System.out.println(millisToLongDHMS((4 * ONE_DAY) + (3 * ONE_HOUR)
            + (2 * ONE_MINUTE) + ONE_SECOND));
        System.out.println(millisToLongDHMS((5 * ONE_DAY) + (4 * ONE_HOUR)
            + ONE_MINUTE + (23 * ONE_SECOND) + 123));
        System.out.println(millisToLongDHMS(42 * ONE_DAY));
        /*
          output :
                0 second
                5 seconds
                1 day, 1 hour
                1 day and 2 seconds
                1 day, 1 hour, 2 minutes
                4 days, 3 hours, 2 minutes and 1 second
                5 days, 4 hours, 1 minute and 23 seconds
                42 days
         */
    }
}

more @Format a duration in milliseconds into a human-readable format

更多@Format以毫秒为单位的持续时间,形成人类可读的格式

#4


33  

I take RealHowTo and Ben J answers and make my own version:

我采用RealHowTo和Ben J的答案并制作我自己的版本:

public class TimeAgo {
public static final List<Long> times = Arrays.asList(
        TimeUnit.DAYS.toMillis(365),
        TimeUnit.DAYS.toMillis(30),
        TimeUnit.DAYS.toMillis(1),
        TimeUnit.HOURS.toMillis(1),
        TimeUnit.MINUTES.toMillis(1),
        TimeUnit.SECONDS.toMillis(1) );
public static final List<String> timesString = Arrays.asList("year","month","day","hour","minute","second");

public static String toDuration(long duration) {

    StringBuffer res = new StringBuffer();
    for(int i=0;i< TimeAgo.times.size(); i++) {
        Long current = TimeAgo.times.get(i);
        long temp = duration/current;
        if(temp>0) {
            res.append(temp).append(" ").append( TimeAgo.timesString.get(i) ).append(temp != 1 ? "s" : "").append(" ago");
            break;
        }
    }
    if("".equals(res.toString()))
        return "0 seconds ago";
    else
        return res.toString();
}
public static void main(String args[]) {
    System.out.println(toDuration(123));
    System.out.println(toDuration(1230));
    System.out.println(toDuration(12300));
    System.out.println(toDuration(123000));
    System.out.println(toDuration(1230000));
    System.out.println(toDuration(12300000));
    System.out.println(toDuration(123000000));
    System.out.println(toDuration(1230000000));
    System.out.println(toDuration(12300000000L));
    System.out.println(toDuration(123000000000L));
}}

which will print the following

这将打印以下内容

0 second ago
1 second ago
12 seconds ago
2 minutes ago
20 minutes ago
3 hours ago
1 day ago
14 days ago
4 months ago
3 years ago

#5


9  

This is based on RealHowTo's answer so if you like it, give him/her some love too.

这是基于RealHowTo的答案,所以如果你喜欢它,也要给他/她一些爱。

This cleaned up version allows you to specify the range of time you might be interested in.

此清理版本允许您指定您可能感兴趣的时间范围。

It also handles the " and " part a little differently. I often find when joining strings with a delimiter it's ofter easier to skip the complicated logic and just delete the last delimiter when you're done.

它还处理“和”部分有点不同。我经常发现,当使用分隔符连接字符串时,更容易跳过复杂的逻辑,并在完成后删除最后一个分隔符。

import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.MILLISECONDS;

public class TimeUtils {

    /**
     * Converts time to a human readable format within the specified range
     *
     * @param duration the time in milliseconds to be converted
     * @param max      the highest time unit of interest
     * @param min      the lowest time unit of interest
     */
    public static String formatMillis(long duration, TimeUnit max, TimeUnit min) {
        StringBuilder res = new StringBuilder();

        TimeUnit current = max;

        while (duration > 0) {
            long temp = current.convert(duration, MILLISECONDS);

            if (temp > 0) {
                duration -= current.toMillis(temp);
                res.append(temp).append(" ").append(current.name().toLowerCase());
                if (temp < 2) res.deleteCharAt(res.length() - 1);
                res.append(", ");
            }

            if (current == min) break;

            current = TimeUnit.values()[current.ordinal() - 1];
        }

        // clean up our formatting....

        // we never got a hit, the time is lower than we care about
        if (res.lastIndexOf(", ") < 0) return "0 " + min.name().toLowerCase();

        // yank trailing  ", "
        res.deleteCharAt(res.length() - 2);

        //  convert last ", " to " and"
        int i = res.lastIndexOf(", ");
        if (i > 0) {
            res.deleteCharAt(i);
            res.insert(i, " and");
        }

        return res.toString();
    }
}

Little code to give it a whirl:

很少的代码让它旋转:

import static java.util.concurrent.TimeUnit.*;

public class Main {

    public static void main(String args[]) {
        long[] durations = new long[]{
            123,
            SECONDS.toMillis(5) + 123,
            DAYS.toMillis(1) + HOURS.toMillis(1),
            DAYS.toMillis(1) + SECONDS.toMillis(2),
            DAYS.toMillis(1) + HOURS.toMillis(1) + MINUTES.toMillis(2),
            DAYS.toMillis(4) + HOURS.toMillis(3) + MINUTES.toMillis(2) + SECONDS.toMillis(1),
            DAYS.toMillis(5) + HOURS.toMillis(4) + MINUTES.toMillis(1) + SECONDS.toMillis(23) + 123,
            DAYS.toMillis(42)
        };

        for (long duration : durations) {
            System.out.println(TimeUtils.formatMillis(duration, DAYS, SECONDS));
        }

        System.out.println("\nAgain in only hours and minutes\n");

        for (long duration : durations) {
            System.out.println(TimeUtils.formatMillis(duration, HOURS, MINUTES));
        }
    }

}

Which will output the following:

这将输出以下内容:

0 seconds
5 seconds 
1 day and 1 hour 
1 day and 2 seconds 
1 day, 1 hour and 2 minutes 
4 days, 3 hours, 2 minutes and 1 second 
5 days, 4 hours, 1 minute and 23 seconds 
42 days 

Again in only hours and minutes

0 minutes
0 minutes
25 hours 
24 hours 
25 hours and 2 minutes 
99 hours and 2 minutes 
124 hours and 1 minute 
1008 hours 

And in case anyone ever needs it, here's a class that will convert any string like the above back into milliseconds. It's pretty useful for allowing people to specify timeouts of various things in readable text.

如果有人需要它,这里有一个类将上面的任何字符串转换回毫秒。它对于允许人们在可读文本中指定各种事物的超时非常有用。

#6


8  

there's a simple way to do this:

这有一个简单的方法:

let's say you want the time 20 minutes ago:

假设你想要20分钟前的时间:

Long minutesAgo = new Long(20);
Date date = new Date();
Date dateIn_X_MinAgo = new Date (date.getTime() - minutesAgo*60*1000);

that's it..

而已..

#7


6  

java.time

Using the java.time framework built into Java 8 and later.

使用Java 8及更高版本中内置的java.time框架。

LocalDateTime t1 = LocalDateTime.of(2015, 1, 1, 0, 0, 0);
LocalDateTime t2 = LocalDateTime.now();
Period period = Period.between(t1.toLocalDate(), t2.toLocalDate());
Duration duration = Duration.between(t1, t2);

System.out.println("First January 2015 is " + period.getYears() + " years ago");
System.out.println("First January 2015 is " + period.getMonths() + " months ago");
System.out.println("First January 2015 is " + period.getDays() + " days ago");
System.out.println("First January 2015 is " + duration.toHours() + " hours ago");
System.out.println("First January 2015 is " + duration.toMinutes() + " minutes ago");

#8


5  

If you looking for a simple "Today", "Yesterday" or "x days ago".

如果你想找一个简单的“今天”,“昨天”或“x天前”。

private String getDaysAgo(Date date){
    long days = (new Date().getTime() - date.getTime()) / 86400000;

    if(days == 0) return "Today";
    else if(days == 1) return "Yesterday";
    else return days + " days ago";
}

#9


5  

About built-in solutions:

关于内置解决方案:

Java does not have any built-in support for formatting relative times, also not Java-8 and its new package java.time. If you only need English and nothing else then and only then a hand-made solution might be acceptable - see the answer of @RealHowTo (although it has the strong disadvantage to not take into account the timezone for the translation of instant deltas to local time units!). Anyway, if you want to avoid home-grown complex workarounds especially for other locales then you need an external library.

Java没有任何内置的格式化相对时间的支持,也没有Java-8及其新的包java.time。如果你只需要英语而不需要其他任何东西,那么只有手工制作的解决方案才可以接受 - 请参阅@RealHowTo的答案(虽然它有一个很大的缺点,就是不考虑将即时增量转换为当地时间的时区单位!)。无论如何,如果你想避免本土复杂的解决方法,特别是对于其他语言环境,那么你需要一个外部库。

In latter case, I recommend to use my library Time4J (or Time4A on Android). It offers greatest flexibility and most i18n-power. The class net.time4j.PrettyTime has seven methods printRelativeTime...(...) for this purpose. Example using a test clock as time source:

在后一种情况下,我建议使用我的库Time4J(或Android上的Time4A)。它提供了最大的灵活性和大多数i18n功率。 net.time4j.PrettyTime类为此目的有七个方法printRelativeTime ...(...)。使用测试时钟作为时间源的示例:

TimeSource<?> clock = () -> PlainTimestamp.of(2015, 8, 1, 10, 24, 5).atUTC();
Moment moment = PlainTimestamp.of(2015, 8, 1, 17, 0).atUTC(); // our input
String durationInDays =
  PrettyTime.of(Locale.GERMAN).withReferenceClock(clock).printRelative(
    moment,
    Timezone.of(EUROPE.BERLIN),
    TimeUnit.DAYS); // controlling the precision
System.out.println(durationInDays); // heute (german word for today)

Another example using java.time.Instant as input:

使用java.time.Instant作为输入的另一个示例:

String relativeTime = 
  PrettyTime.of(Locale.ENGLISH)
    .printRelativeInStdTimezone(Moment.from(Instant.EPOCH));
System.out.println(relativeTime); // 45 years ago

This library supports via its latest version (v4.17) 80 languages and also some country-specific locales (especially for Spanish, English, Arabic, French). The i18n-data are mainly based on the newest CLDR-version v29. Other important reasons why to use this library are good support for plural rules (which are often different from English in other locales), abbreviated format style (for example: "1 sec ago") and expressive ways for taking into account timezones. Time4J is even aware of such exotic details like leap seconds in calculations of relative times (not really important but it forms a message related to the expectation horizon). The compatibility with Java-8 exists due to easily available conversion methods for types like java.time.Instant or java.time.Period.

该库通过其最新版本(v4.17)支持80种语言以及一些特定国家/地区的语言环境(特别是西班牙语,英语,阿拉伯语,法语)。 i18n数据主要基于最新的CLDR版本v29。使用此库的其他重要原因是对多个规则(通常与其他语言环境中的英语不同),缩写格式样式(例如:“1秒前”)以及考虑时区的表达方式的良好支持。 Time4J甚至意识到这些奇特的细节,比如计算相对时间的闰秒(不是很重要,但它形成了与期望视野相关的信息)。由于java.time.Instant或java.time.Period等类型的易于使用的转换方法,因此与Java-8的兼容性存在。

Are there any drawbacks? Only two.

有什么缺点吗?只有两个。

  • The library is not small (also because of its big i18n-data repository).
  • 该库不小(也因为其庞大的i18n数据存储库)。
  • The API is not well known so community knowledge and support are not available yet otherwise the supplied documentation is pretty detailed and comprehensive.
  • API并不为人所知,因此社区知识和支持尚不可用,否则所提供的文档非常详细和全面。

(Compact) alternatives:

(紧凑型)替代品:

If you look for a smaller solution and don't need so many features and are willing to tolerate possible quality issues related to i18n-data then:

如果您寻找更小的解决方案,并且不需要这么多功能,并且愿意容忍与i18n-data相关的可能的质量问题,那么:

  • I would recommend ocpsoft/PrettyTime (support for actually 32 languages (soon 34?) suitable for work with java.util.Date only - see the answer of @ataylor). The industry standard CLDR (from Unicode consortium) with its big community background is unfortunatly not a base of the i18n-data so further enhancements or improvements of data can take a while...

    我建议ocpsoft / PrettyTime(实际支持32种语言(很快34?)只适合与java.util.Date一起工作 - 请参阅@ataylor的答案)。具有巨大社区背景的行业标准CLDR(来自Unicode联盟)不幸地不是i18n数据的基础,因此数据的进一步增强或改进可能需要一段时间......

  • If you are on Android then the helper class android.text.format.DateUtils is a slim built-in alternative (see other comments and answers here, with the disadvantage that it has no support for years and months. And I am sure that only very few people like the API-style of this helper class.

    如果你在Android上,那么辅助类android.text.format.DateUtils是一个纤薄的内置替代品(请参阅其他评论和答案,缺点是它几年和几个月都没有支持。而且我确信只有很少有人喜欢这个助手类的API风格。

  • If you are a fan of Joda-Time then you can look at its class PeriodFormat (support for 14 languages in release v2.9.4, on the other side: Joda-Time is surely not compact, too, so I mention it here just for completeness). This library is not a real answer because relative times are not supported at all. You will need to append the literal " ago" at least (and manually stripping off all lower units from generated list formats - awkward). Unlike Time4J or Android-DateUtils, it has no special support for abbreviations or automatic switching from relative times to absolute time representations. Like PrettyTime, it is totally dependent on the unconfirmed contributions of private members of the Java-community to its i18n-data.

    如果您是Joda-Time的粉丝,那么您可以查看它的类PeriodFormat(在版本v2.9.4中支持14种语言,另一方面:Joda-Time肯定也不紧凑,所以我在这里提到它只是为了完整性)。这个库不是真正的答案,因为根本不支持相对时间。您至少需要附加文字“之前”(并从生成的列表格式中手动剥离所有较低的单位 - 笨拙)。与Time4J或Android-DateUtils不同,它没有特别支持缩写或从相对时间到绝对时间表示的自动切换。与PrettyTime一样,它完全依赖于Java社区的私有成员对其i18n数据的未经证实的贡献。

#10


4  

I created a simple Java timeago port of the jquery-timeago plug-in that does what you are asking for.

我创建了一个jquery-timeago插件的简单Java timeago端口,可以满足您的需求。

TimeAgo time = new TimeAgo();
String minutes = time.timeAgo(System.currentTimeMillis() - (15*60*1000)); // returns "15 minutes ago"

#11


3  

The joda-time package, has the notion of Periods. You can do arithmetic with Periods and DateTimes.

joda-time包,有Periods的概念。您可以使用Periods和DateTimes进行算术运算。

From the docs:

来自文档:

public boolean isRentalOverdue(DateTime datetimeRented) {
  Period rentalPeriod = new  Period().withDays(2).withHours(12);
  return datetimeRented.plus(rentalPeriod).isBeforeNow();
}

#12


3  

You Can use this function to calculate time ago

您可以使用此功能计算时间

 private String timeAgo(long time_ago) {
        long cur_time = (Calendar.getInstance().getTimeInMillis()) / 1000;
        long time_elapsed = cur_time - time_ago;
        long seconds = time_elapsed;
        int minutes = Math.round(time_elapsed / 60);
        int hours = Math.round(time_elapsed / 3600);
        int days = Math.round(time_elapsed / 86400);
        int weeks = Math.round(time_elapsed / 604800);
        int months = Math.round(time_elapsed / 2600640);
        int years = Math.round(time_elapsed / 31207680);

        // Seconds
        if (seconds <= 60) {
            return "just now";
        }
        //Minutes
        else if (minutes <= 60) {
            if (minutes == 1) {
                return "one minute ago";
            } else {
                return minutes + " minutes ago";
            }
        }
        //Hours
        else if (hours <= 24) {
            if (hours == 1) {
                return "an hour ago";
            } else {
                return hours + " hrs ago";
            }
        }
        //Days
        else if (days <= 7) {
            if (days == 1) {
                return "yesterday";
            } else {
                return days + " days ago";
            }
        }
        //Weeks
        else if (weeks <= 4.3) {
            if (weeks == 1) {
                return "a week ago";
            } else {
                return weeks + " weeks ago";
            }
        }
        //Months
        else if (months <= 12) {
            if (months == 1) {
                return "a month ago";
            } else {
                return months + " months ago";
            }
        }
        //Years
        else {
            if (years == 1) {
                return "one year ago";
            } else {
                return years + " years ago";
            }
        }
    }

1) Here time_ago is in microsecond

1)这里time_ago是微秒

#13


2  

It's not pretty...but the closest I can think of is using Joda-Time (as described in this post: How to calculate elapsed time from now with Joda Time?

它并不漂亮...但我能想到的最接近的是使用Joda-Time(如本文所述:如何用Joda Time计算从现在开始的经过时间?

#14


2  

In case you're developing an app for Android, it provides the utility class DateUtils for all such requirements. Take a look at the DateUtils#getRelativeTimeSpanString() utility method.

如果您正在为Android开发应用程序,它会为所有此类要求提供实用程序类DateUtils。看一下DateUtils#getRelativeTimeSpanString()实用程序方法。

From the docs for

来自文档

CharSequence getRelativeTimeSpanString (long time, long now, long minResolution)

CharSequence getRelativeTimeSpanString(很长一段时间,很长一段时间,很长的minResolution)

Returns a string describing 'time' as a time relative to 'now'. Time spans in the past are formatted like "42 minutes ago". Time spans in the future are formatted like "In 42 minutes".

返回一个字符串,描述'time'作为相对于'now'的时间。过去的时间跨度格式为“42分钟前”。未来的时间跨度格式为“在42分钟内”。

You'll be passing your timestamp as time and System.currentTimeMillis() as now. The minResolution lets you specify the minimum timespan to report.

你将把时间戳作为时间和System.currentTimeMillis()传递给你。 minResolution允许您指定要报告的最小时间跨度。

For example, a time 3 seconds in the past will be reported as "0 minutes ago" if this is set to MINUTE_IN_MILLIS. Pass one of 0, MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS, WEEK_IN_MILLIS etc.

例如,如果设置为MINUTE_IN_MILLIS,则过去3秒的时间将报告为“0分钟前”。传递0,MINUTE_IN_MILLIS,HOUR_IN_MILLIS,DAY_IN_MILLIS,WEEK_IN_MILLIS等中的一个。

#15


2  

This is a better code if we consider performance.It reduces the number of calculations. Reason Minutes are calculated only if the number of seconds is greater than 60 and Hours are calculated only if the number of minutes is greater than 60 and so on...

如果我们考虑性能,这是一个更好的代码。它减少了计算次数。仅当秒数大于60时计算原因分钟,并且仅在分钟数大于60时计算小时数等等...

class timeAgo {

static String getTimeAgo(long time_ago) {
    time_ago=time_ago/1000;
    long cur_time = (Calendar.getInstance().getTimeInMillis())/1000 ;
    long time_elapsed = cur_time - time_ago;
    long seconds = time_elapsed;
   // Seconds
    if (seconds <= 60) {
        return "Just now";
    }
    //Minutes
    else{
        int minutes = Math.round(time_elapsed / 60);

        if (minutes <= 60) {
            if (minutes == 1) {
                return "a minute ago";
            } else {
                return minutes + " minutes ago";
            }
        }
        //Hours
        else {
            int hours = Math.round(time_elapsed / 3600);
            if (hours <= 24) {
                if (hours == 1) {
                    return "An hour ago";
                } else {
                    return hours + " hrs ago";
                }
            }
            //Days
            else {
                int days = Math.round(time_elapsed / 86400);
                if (days <= 7) {
                    if (days == 1) {
                        return "Yesterday";
                    } else {
                        return days + " days ago";
                    }
                }
                //Weeks
                else {
                    int weeks = Math.round(time_elapsed / 604800);
                    if (weeks <= 4.3) {
                        if (weeks == 1) {
                            return "A week ago";
                        } else {
                            return weeks + " weeks ago";
                        }
                    }
                    //Months
                    else {
                        int months = Math.round(time_elapsed / 2600640);
                        if (months <= 12) {
                            if (months == 1) {
                                return "A month ago";
                            } else {
                                return months + " months ago";
                            }
                        }
                        //Years
                        else {
                            int years = Math.round(time_elapsed / 31207680);
                            if (years == 1) {
                                return "One year ago";
                            } else {
                                return years + " years ago";
                            }
                        }
                    }
                }
            }
        }
    }

}

}

#16


1  

After long research i found this.

经过长时间的研究我发现了这个

    public class GetTimeLapse {
    public static String getlongtoago(long createdAt) {
        DateFormat userDateFormat = new SimpleDateFormat("E MMM dd HH:mm:ss Z yyyy");
        DateFormat dateFormatNeeded = new SimpleDateFormat("MM/dd/yyyy HH:MM:SS");
        Date date = null;
        date = new Date(createdAt);
        String crdate1 = dateFormatNeeded.format(date);

        // Date Calculation
        DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
        crdate1 = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(date);

        // get current date time with Calendar()
        Calendar cal = Calendar.getInstance();
        String currenttime = dateFormat.format(cal.getTime());

        Date CreatedAt = null;
        Date current = null;
        try {
            CreatedAt = dateFormat.parse(crdate1);
            current = dateFormat.parse(currenttime);
        } catch (java.text.ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // Get msec from each, and subtract.
        long diff = current.getTime() - CreatedAt.getTime();
        long diffSeconds = diff / 1000;
        long diffMinutes = diff / (60 * 1000) % 60;
        long diffHours = diff / (60 * 60 * 1000) % 24;
        long diffDays = diff / (24 * 60 * 60 * 1000);

        String time = null;
        if (diffDays > 0) {
            if (diffDays == 1) {
                time = diffDays + "day ago ";
            } else {
                time = diffDays + "days ago ";
            }
        } else {
            if (diffHours > 0) {
                if (diffHours == 1) {
                    time = diffHours + "hr ago";
                } else {
                    time = diffHours + "hrs ago";
                }
            } else {
                if (diffMinutes > 0) {
                    if (diffMinutes == 1) {
                        time = diffMinutes + "min ago";
                    } else {
                        time = diffMinutes + "mins ago";
                    }
                } else {
                    if (diffSeconds > 0) {
                        time = diffSeconds + "secs ago";
                    }
                }

            }

        }
        return time;
    }
}

#17


1  

For Android Exactly like Ravi said, but since lots of people want to just copy paste the thing here it is.

对于Android完全像Ravi所说的那样,但由于很多人只想复制粘贴这里的东西。

  try {
      SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
      Date dt = formatter.parse(date_from_server);
      CharSequence output = DateUtils.getRelativeTimeSpanString (dt.getTime());
      your_textview.setText(output.toString());
    } catch (Exception ex) {
      ex.printStackTrace();
      your_textview.setText("");
    }

Explanation for people that have more time

对有更多时间的人的解释

  1. You get the data from somewhere. First you have to figure out it's format.
  2. 你从某个地方获得数据。首先,你必须弄清楚它的格式。

Ex. I get the data from a server in the format Wed, 27 Jan 2016 09:32:35 GMT [this is probably NOT your case]

防爆。我从格林威治标准时间2016年1月27日09:32:35格式的服务器获取数据[这可能不是你的情况]

this is translated into

这被翻译成

SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");

SimpleDateFormat formatter = new SimpleDateFormat(“EEE,dd MMM yyyy HH:mm:ss Z”);

how do I know it? Read the documentation here.

我怎么知道的?阅读此处的文档。

Then after I parse it I get a date. that date I put in the getRelativeTimeSpanString (without any additional parameters is fine by me, to be default to minutes)

然后我解析它后得到一个约会。那个日期我放入了getRelativeTimeSpanString(没有任何额外的参数对我来说很好,默认为几分钟)

You WILL get an exception if you didn't figure out the correct parsing String, Something like: exception at character 5. Look at character 5, and correct your initial parsing string.. You might get another exception, repeat this steps until you have the correct formula.

如果你没有找到正确的解析字符串,你会得到一个异常,例如:字符5处的异常。查看字符5,并更正你的初始解析字符串..你可能会得到另一个异常,重复这些步骤直到你有正确的公式。

#18


1  

Based on a bunch of answers here, I created the following for my use case.

基于这里的一堆答案,我为我的用例创建了以下内容。

Example usage:

用法示例:

String relativeDate = String.valueOf(
                TimeUtils.getRelativeTime( 1000L * myTimeInMillis() ));

import java.util.Arrays;
import java.util.List;

import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;

/**
 * Utilities for dealing with dates and times
 */
public class TimeUtils {

    public static final List<Long> times = Arrays.asList(
        DAYS.toMillis(365),
        DAYS.toMillis(30),
        DAYS.toMillis(7),
        DAYS.toMillis(1),
        HOURS.toMillis(1),
        MINUTES.toMillis(1),
        SECONDS.toMillis(1)
    );

    public static final List<String> timesString = Arrays.asList(
        "yr", "mo", "wk", "day", "hr", "min", "sec"
    );

    /**
     * Get relative time ago for date
     *
     * NOTE:
     *  if (duration > WEEK_IN_MILLIS) getRelativeTimeSpanString prints the date.
     *
     * ALT:
     *  return getRelativeTimeSpanString(date, now, SECOND_IN_MILLIS, FORMAT_ABBREV_RELATIVE);
     *
     * @param date String.valueOf(TimeUtils.getRelativeTime(1000L * Date/Time in Millis)
     * @return relative time
     */
    public static CharSequence getRelativeTime(final long date) {
        return toDuration( Math.abs(System.currentTimeMillis() - date) );
    }

    private static String toDuration(long duration) {
        StringBuilder sb = new StringBuilder();
        for(int i=0;i< times.size(); i++) {
            Long current = times.get(i);
            long temp = duration / current;
            if (temp > 0) {
                sb.append(temp)
                  .append(" ")
                  .append(timesString.get(i))
                  .append(temp > 1 ? "s" : "")
                  .append(" ago");
                break;
            }
        }
        return sb.toString().isEmpty() ? "now" : sb.toString();
    }
}

#19


0  

Here is my Java Implementation of this

这是我的Java实现

    public static String relativeDate(Date date){
    Date now=new Date();
    if(date.before(now)){
    int days_passed=(int) TimeUnit.MILLISECONDS.toDays(now.getTime() - date.getTime());
    if(days_passed>1)return days_passed+" days ago";
    else{
        int hours_passed=(int) TimeUnit.MILLISECONDS.toHours(now.getTime() - date.getTime());
        if(hours_passed>1)return days_passed+" hours ago";
        else{
            int minutes_passed=(int) TimeUnit.MILLISECONDS.toMinutes(now.getTime() - date.getTime());
            if(minutes_passed>1)return minutes_passed+" minutes ago";
            else{
                int seconds_passed=(int) TimeUnit.MILLISECONDS.toSeconds(now.getTime() - date.getTime());
                return seconds_passed +" seconds ago";
            }
        }
    }

    }
    else
    {
        return new SimpleDateFormat("HH:mm:ss MM/dd/yyyy").format(date).toString();
    }
  }

#20


0  

it works for me

这个对我有用

public class TimeDifference {
    int years;
    int months;
    int days;
    int hours;
    int minutes;
    int seconds;
    String differenceString;

    public TimeDifference(@NonNull Date curdate, @NonNull Date olddate) {

        float diff = curdate.getTime() - olddate.getTime();
        if (diff >= 0) {
            int yearDiff = Math.round((diff / (AppConstant.aLong * AppConstant.aFloat)) >= 1 ? (diff / (AppConstant.aLong * AppConstant.aFloat)) : 0);
            if (yearDiff > 0) {
                years = yearDiff;
                setDifferenceString(years + (years == 1 ? " year" : " years") + " ago");
            } else {
                int monthDiff = Math.round((diff / AppConstant.aFloat) >= 1 ? (diff / AppConstant.aFloat) : 0);
                if (monthDiff > 0) {
                    if (monthDiff > AppConstant.ELEVEN) {
                        monthDiff = AppConstant.ELEVEN;
                    }
                    months = monthDiff;
                    setDifferenceString(months + (months == 1 ? " month" : " months") + " ago");
                } else {
                    int dayDiff = Math.round((diff / (AppConstant.bFloat)) >= 1 ? (diff / (AppConstant.bFloat)) : 0);
                    if (dayDiff > 0) {
                        days = dayDiff;
                        if (days == AppConstant.THIRTY) {
                            days = AppConstant.TWENTYNINE;
                        }
                        setDifferenceString(days + (days == 1 ? " day" : " days") + " ago");
                    } else {
                        int hourDiff = Math.round((diff / (AppConstant.cFloat)) >= 1 ? (diff / (AppConstant.cFloat)) : 0);
                        if (hourDiff > 0) {
                            hours = hourDiff;
                            setDifferenceString(hours + (hours == 1 ? " hour" : " hours") + " ago");
                        } else {
                            int minuteDiff = Math.round((diff / (AppConstant.dFloat)) >= 1 ? (diff / (AppConstant.dFloat)) : 0);
                            if (minuteDiff > 0) {
                                minutes = minuteDiff;
                                setDifferenceString(minutes + (minutes == 1 ? " minute" : " minutes") + " ago");
                            } else {
                                int secondDiff = Math.round((diff / (AppConstant.eFloat)) >= 1 ? (diff / (AppConstant.eFloat)) : 0);
                                if (secondDiff > 0) {
                                    seconds = secondDiff;
                                } else {
                                    seconds = 1;
                                }
                                setDifferenceString(seconds + (seconds == 1 ? " second" : " seconds") + " ago");
                            }
                        }
                    }

                }
            }

        } else {
            setDifferenceString("Just now");
        }

    }

    public String getDifferenceString() {
        return differenceString;
    }

    public void setDifferenceString(String differenceString) {
        this.differenceString = differenceString;
    }

    public int getYears() {
        return years;
    }

    public void setYears(int years) {
        this.years = years;
    }

    public int getMonths() {
        return months;
    }

    public void setMonths(int months) {
        this.months = months;
    }

    public int getDays() {
        return days;
    }

    public void setDays(int days) {
        this.days = days;
    }

    public int getHours() {
        return hours;
    }

    public void setHours(int hours) {
        this.hours = hours;
    }

    public int getMinutes() {
        return minutes;
    }

    public void setMinutes(int minutes) {
        this.minutes = minutes;
    }

    public int getSeconds() {
        return seconds;
    }

    public void setSeconds(int seconds) {
        this.seconds = seconds;
    } }

#21


0  

This is the very basic script. its easy to improvized.
Result : (XXX Hours Ago), or (XX Days Ago/Yesterday/Today)

这是非常基本的脚本。它易于改进。结果:(XXX小时前),或(XX天前/昨天/今天)

<span id='hourpost'></span>
,or
<span id='daypost'></span>

<script>
var postTime = new Date('2017/6/9 00:01'); 
var now = new Date();
var difference = now.getTime() - postTime.getTime();
var minutes = Math.round(difference/60000);
var hours = Math.round(minutes/60);
var days = Math.round(hours/24);

var result;
if (days < 1) {
result = "Today";
} else if (days < 2) {
result = "Yesterday";
} else {
result = days + " Days ago";
}

document.getElementById("hourpost").innerHTML = hours + "Hours Ago" ;
document.getElementById("daypost").innerHTML = result ;
</script>