How to calculate “time ago” in Java?
在Ruby on Rails中,有一项功能允许您获取任何Date并打印出它的"很久以前"。
例如:
1 2 3 4 5 | 8 minutes ago 8 hours ago 8 days ago 8 months ago 8 years ago |
有没有简单的方法可以在Java中做到这一点?
看一下PrettyTime库。
使用起来非常简单:
1 2 3 4 5 |
您还可以传递国际化消息的语言环境:
1 2 3 |
如评论中所述,Android在
您是否考虑过TimeUnit枚举?对于这种事情可能非常有用
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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(); } |
我接受RealHowTo和Ben J的答案,并制作自己的版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 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)); }} |
这将打印以下内容
1 2 3 4 5 6 7 8 9 10 | 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 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | 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 */ } } |
更多@将持续时间(以毫秒为单位)格式化为人类可读的格式
这基于RealHowTo的答案,因此,如果您喜欢它,也请给他/她一些爱。
此清理版本允许您指定可能感兴趣的时间范围。
它对"和"部分的处理也有所不同。我经常发现,使用分隔符连接字符串时,跳过复杂的逻辑并在完成后仅删除最后一个分隔符会更容易。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | 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(); } } |
小代码让它旋转:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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("\ Again in only hours and minutes\ "); for (long duration : durations) { System.out.println(TimeUtils.formatMillis(duration, HOURS, MINUTES)); } } } |
将输出以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 |
万一有人需要它,这是一个类,它将把上述字符串转换成毫秒。允许人们在可读文本中指定各种内容的超时非常有用。
有一个简单的方法可以做到这一点:
假设您想要20分钟前的时间:
1 2 3 |
而已..
关于内置解决方案:
Java不支持格式化相对时间,也没有Java-8及其新包
在后一种情况下,我建议使用我的库Time4J(或Android上的Time4A)。它提供了最大的灵活性和最强大的功能。为此,类net.time4j.PrettyTime具有七个方法
1 2 3 4 5 6 7 8 | 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) |
使用
1 2 3 4 |
该库通过其最新版本(v4.17)支持80种语言,并且还支持某些国家/地区特定的语言环境(尤其是西班牙语,英语,阿拉伯语,法语)。 i18n数据主要基于最新的CLDR版本v29。使用此库的其他重要原因还包括对复数规则(在其他地区通常与英语不同的规则)的良好支持,缩写的格式样式(例如:" 1秒前")以及考虑时区的表达方式。 Time4J甚至在相对时间的计算中还知道诸如跳秒之类的奇特细节(虽然并不重要,但它形成了与期望范围相关的信息)。与Java-8的兼容性是由于
有什么缺点吗?只有两个。
- 该库不小(也是由于其较大的i18n数据存储库)。
- 该API尚不为人所知,因此尚无法获得社区知识和支持,否则提供的文档非常详细和全面。
(紧凑)替代方案:
如果您寻找较小的解决方案并且不需要太多功能并且愿意忍受与i18n-data相关的质量问题,那么:
-
我建议ocpsoft / PrettyTime(实际上支持32种语言(34号很快开始?)仅适用于
java.util.Date -请参见@ataylor的答案)。不幸的是,行业标准CLDR(来自Unicode联盟)具有很大的社区背景,而不是i18n数据的基础,因此,进一步的数据增强或改进可能需要一段时间... -
如果您使用的是Android,则帮助程序类android.text.format.DateUtils是一种苗条的内置替代方法(请参见此处的其他评论和答案,其缺点是多年来一直没有支持。我敢肯定,只有很少有人喜欢此帮助程序类的API样式。
-
如果您是Joda-Time的粉丝,那么可以看看它的类PeriodFormat(另一方面,在v2.9.4版中支持14种语言:Joda-Time当然也不紧凑,因此在这里我仅提及它是为了完整性)。这个库不是真正的答案,因为根本不支持相对时间。您至少需要附加文字"以前"(并从生成的列表格式中手动剥离所有较低的单元-尴尬)。与Time4J或Android-DateUtils不同,它没有对缩写词的特殊支持或从相对时间到绝对时间表示的自动切换。与PrettyTime一样,它完全取决于Java社区的私有成员对其i18n数据的未确认贡献。
如果您要查找简单的"今天","昨天"或" x天前"。
1 2 3 4 5 6 7 |
java.time
使用Java 8及更高版本中内置的java.time框架。
1 2 3 4 5 6 7 8 9 10 | 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"); |
基于此处的一系列答案,我为用例创建了以下内容。
用法示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | 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(); } } |
我创建了一个简单的jquery-timeago插件的Java timeago端口,它可以满足您的要求。
1 2 |
如果您要开发用于Android的应用程序,它将为所有此类需求提供实用程序类DateUtils。看一下DateUtils#getRelativeTimeSpanString()实用程序方法。
来自的文档
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".
您现在将传递
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.
您可以使用此功能计算时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | 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)这里time_ago以微秒为单位
joda-time程序包具有句点的概念。您可以使用Periods和DateTimes进行算术运算。
从文档:
1 2 3 4 | public boolean isRentalOverdue(DateTime datetimeRented) { Period rentalPeriod = new Period().withDays(2).withHours(12); return datetimeRented.plus(rentalPeriod).isBeforeNow(); } |
java.time
Habsq的答案具有正确的想法,但有错误的方法。
对于未附加到时间轴上的年-月-日-天的时间范围,请使用
首先使用
1 2 3 | Instant now = Instant.now(); // Capture the current moment as seen in UTC. Instant then = now.minus( 8L , ChronoUnit.HOURS ).minus( 8L , ChronoUnit.MINUTES ).minus( 8L , ChronoUnit.SECONDS ); Duration d = Duration.between( then , now ); |
生成小时,分钟和秒的文本。
1 2 3 4 | // Generate text by calling `to…Part` methods. String output = d.toHoursPart() +" hours ago\ " + d.toMinutesPart() +" minutes ago\ " + d.toSecondsPart() +" seconds ago"; |
转储到控制台。
From: 2019-06-04T11:53:55.714965Z to: 2019-06-04T20:02:03.714965Z
8 hours ago
8 minutes ago
8 seconds ago
首先获取当前日期。
时区对于确定日期至关重要。在任何给定时刻,日期都会在全球范围内变化。例如,法国巴黎午夜过后的几分钟是新的一天,而在魁北克蒙特利尔仍然是"昨天"。
如果未指定时区,则JVM隐式应用其当前的默认时区。该默认值可能会在运行时(!)期间随时更改,因此您的结果可能会有所不同。最好将您的期望/期望时区明确指定为参数。如果紧急,请与您的用户确认区域。
以
1 2 | ZoneId z = ZoneId.of("America/Montreal" ) ; LocalDate today = LocalDate.now( z ) ; |
重新创建日期八天,几个月和几年前。
1 | LocalDate then = today.minusYears( 8 ).minusMonths( 8 ).minusDays( 7 ); // Notice the 7 days, not 8, because of granularity of months. |
计算经过的时间。
1 | Period p = Period.between( then , today ); |
构建"时间之前"片段的字符串。
1 2 3 | String output = p.getDays() +" days ago\ " + p.getMonths() +" months ago\ " + p.getYears() +" years ago"; |
转储到控制台。
From: 2010-09-27 to: 2019-06-04
8 days ago
8 months ago
8 years ago
关于java.time
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧版旧式日期时间类,例如
要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC驱动程序。不需要字符串,不需要
在哪里获取java.time类?
-
Java SE 8,Java SE 9,Java SE 10,Java SE 11和更高版本-标准Java API的一部分,具有捆绑的实现。
- Java 9添加了一些次要功能和修复。
-
Java SE 6和Java SE 7
- 大多数Java.time功能都在ThreeTen-Backport中反向移植到Java 6和7。
-
安卓系统
- 更高版本的Android捆绑了java.time类的实现。
- 对于早期的Android(<26),ThreeTenABP项目改编了ThreeTen-Backport(如上所述)。请参阅如何使用ThreeTenABP…。
ThreeTen-Extra项目使用其他类扩展了java.time。该项目是将来可能向java.time添加内容的试验场。您可能会在这里找到一些有用的类,例如
它不是很漂亮...但是我能想到的最接近的是使用Joda-Time(如本文所述:如何使用Joda Time计算从现在开始的经过时间?
如果考虑性能,这是更好的代码,它减少了计算数量。
原因
仅当秒数大于60时才计算分钟数,仅当分钟数大于60时才计算小时数,依此类推...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | 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"; } } } } } } } } } |
经过长期的研究,我发现了这一点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | 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; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | private const val SECOND_MILLIS = 1 private const val MINUTE_MILLIS = 60 * SECOND_MILLIS private const val HOUR_MILLIS = 60 * MINUTE_MILLIS private const val DAY_MILLIS = 24 * HOUR_MILLIS object TimeAgo { fun timeAgo(time: Int): String { val now = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) if (time > now || time <= 0) { return"in the future" } val diff = now - time return when { diff < MINUTE_MILLIS ->"Just now" diff < 2 * MINUTE_MILLIS ->"a minute ago" diff < 60 * MINUTE_MILLIS ->"${diff / MINUTE_MILLIS} minutes ago" diff < 2 * HOUR_MILLIS ->"an hour ago" diff < 24 * HOUR_MILLIS ->"${diff / HOUR_MILLIS} hours ago" diff < 48 * HOUR_MILLIS ->"yesterday" else ->"${diff / DAY_MILLIS} days ago" } } |
}
呼叫
val字符串= timeAgo(unixTimeStamp)
在Kotlin得到时间
对于Android
就像拉维所说的一样,但是由于很多人只想复制粘贴内容,所以就在这里。
1 2 3 4 5 6 7 8 9 | 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(""); } |
给更多时间的人的解释
例如我从服务器获取数据的格式为
2016年1月27日,星期三09:32:35 GMT [这可能不是您的情况]
这被翻译成
SimpleDateFormat formatter = new SimpleDateFormat(" EEE,dd MMM yyyy HH:mm:ss Z");
我怎么知道在此处阅读文档。
然后,我解析它后得到一个日期。我输入getRelativeTimeSpanString的那个日期(没有任何其他参数对我来说很好,默认为分钟)
如果您没有弄清楚正确的解析字符串,将会得到一个异常,例如:字符5处的异常。请看字符5,并更正您的初始解析字符串。正确的公式。
如在Whatsapp通知中看到的,getrelativeDateTime函数将为您提供日期时间。
要获取将来的相对日期时间,请为其添加条件。 这是专门为获取日期时间(如Whatsapp通知)而创建的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | private static String getRelativeDateTime(long date) { SimpleDateFormat DateFormat = new SimpleDateFormat("MMM dd, yyyy", Locale.getDefault()); SimpleDateFormat TimeFormat = new SimpleDateFormat(" hh:mm a", Locale.getDefault()); long now = Calendar.getInstance().getTimeInMillis(); long startOfDay = StartOfDay(Calendar.getInstance().getTime()); String Day =""; String Time =""; long millSecInADay = 86400000; long oneHour = millSecInADay / 24; long differenceFromNow = now - date; if (date > startOfDay) { if (differenceFromNow < (oneHour)) { int minute = (int) (differenceFromNow / (60000)); if (minute == 0) { int sec = (int) differenceFromNow / 1000; if (sec == 0) { Time ="Just Now"; } else if (sec == 1) { Time = sec +" second ago"; } else { Time = sec +" seconds ago"; } } else if (minute == 1) { Time = minute +" minute ago"; } else if (minute < 60) { Time = minute +" minutes ago"; } } else { Day ="Today,"; } } else if (date > (startOfDay - millSecInADay)) { Day ="Yesterday,"; } else if (date > (startOfDay - millSecInADay * 7)) { int days = (int) (differenceFromNow / millSecInADay); Day = days +" Days ago,"; } else { Day = DateFormat.format(date); } if (Time.isEmpty()) { Time = TimeFormat.format(date); } return Day + Time; } public static long StartOfDay(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); return calendar.getTimeInMillis(); } |
这是我的测试用例,希望对您有帮助:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | val currentCalendar = Calendar.getInstance() currentCalendar.set(2019, 6, 2, 5, 31, 0) val targetCalendar = Calendar.getInstance() targetCalendar.set(2019, 6, 2, 5, 30, 0) val diffTs = currentCalendar.timeInMillis - targetCalendar.timeInMillis val diffMins = TimeUnit.MILLISECONDS.toMinutes(diffTs) val diffHours = TimeUnit.MILLISECONDS.toHours(diffTs) val diffDays = TimeUnit.MILLISECONDS.toDays(diffTs) val diffWeeks = TimeUnit.MILLISECONDS.toDays(diffTs) / 7 val diffMonths = TimeUnit.MILLISECONDS.toDays(diffTs) / 30 val diffYears = TimeUnit.MILLISECONDS.toDays(diffTs) / 365 val newTs = when { diffYears >= 1 ->"Years $diffYears" diffMonths >= 1 ->"Months $diffMonths" diffWeeks >= 1 ->"Weeks $diffWeeks" diffDays >= 1 ->"Days $diffDays" diffHours >= 1 ->"Hours $diffHours" diffMins >= 1 ->"Mins $diffMins" else ->"now" } |
以下解决方案全部使用纯Java:
选项1:不舍入,仅使用最大时间容器
以下功能将仅显示最大的时间容器,例如,如果实际经过时间为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public String formatTimeAgo(long millis) { String[] ids = new String[]{"second","minute","hour","day","month","year"}; long seconds = millis / 1000; long minutes = seconds / 60; long hours = minutes / 60; long days = hours / 24; long months = days / 30; long years = months / 12; ArrayList<Long> times = new ArrayList<>(Arrays.asList(years, months, days, hours, minutes, seconds)); for(int i = 0; i < times.size(); i++) { if(times.get(i) != 0) { long value = times.get(i).intValue(); return value +"" + ids[ids.length - 1 - i] + (value == 1 ?"" :"s") +" ago"; } } return"0 seconds ago"; } |
选项2:四舍五入
只需用Math.round(...)语句包装要舍入的时间容器,因此,如果要将
这是我的Java实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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(); } } |
您可以使用Java的Library RelativeDateTimeFormatter,它确实可以做到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | RelativeDateTimeFormatter fmt = RelativeDateTimeFormatter.getInstance(); fmt.format(1, Direction.NEXT, RelativeUnit.DAYS); //"in 1 day" fmt.format(3, Direction.NEXT, RelativeUnit.DAYS); //"in 3 days" fmt.format(3.2, Direction.LAST, RelativeUnit.YEARS); //"3.2 years ago" fmt.format(Direction.LAST, AbsoluteUnit.SUNDAY); //"last Sunday" fmt.format(Direction.THIS, AbsoluteUnit.SUNDAY); //"this Sunday" fmt.format(Direction.NEXT, AbsoluteUnit.SUNDAY); //"next Sunday" fmt.format(Direction.PLAIN, AbsoluteUnit.SUNDAY); //"Sunday" fmt.format(Direction.LAST, AbsoluteUnit.DAY); //"yesterday" fmt.format(Direction.THIS, AbsoluteUnit.DAY); //"today" fmt.format(Direction.NEXT, AbsoluteUnit.DAY); //"tomorrow" fmt.format(Direction.PLAIN, AbsoluteUnit.NOW); //"now" |
为此,在本示例中,我已经完成了
在string.xml中添加以下值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <string name="lbl_justnow">Just Now</string> <string name="lbl_seconds_ago">seconds ago</string> <string name="lbl_min_ago">min ago</string> <string name="lbl_mins_ago">mins ago</string> <string name="lbl_hr_ago">hr ago</string> <string name="lbl_hrs_ago">hrs ago</string> <string name="lbl_day_ago">day ago</string> <string name="lbl_days_ago">days ago</string> <string name="lbl_lstweek_ago">last week</string> <string name="lbl_week_ago">weeks ago</string> <string name="lbl_onemonth_ago">1 month ago</string> <string name="lbl_month_ago">months ago</string> <string name="lbl_oneyear_ago">last year</string> <string name="lbl_year_ago">years ago</string> |
Java代码尝试下面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | public String getFormatDate(String postTime1) { Calendar cal=Calendar.getInstance(); Date now=cal.getTime(); String disTime=""; try { Date postTime; //2018-09-05T06:40:46.183Z postTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(postTime1); long diff=(now.getTime()-postTime.getTime()+18000)/1000; //for months Calendar calObj = Calendar.getInstance(); calObj.setTime(postTime); int m=calObj.get(Calendar.MONTH); calObj.setTime(now); SimpleDateFormat monthFormatter = new SimpleDateFormat("MM"); // output month int mNow = Integer.parseInt(monthFormatter.format(postTime)); diff = diff-19800; if(diff<15) { //below 15 sec disTime = getResources().getString(R.string.lbl_justnow); } else if(diff<60) { //below 1 min disTime= diff+""+getResources().getString(R.string.lbl_seconds_ago); } else if(diff<3600) {//below 1 hr // convert min long temp=diff/60; if(temp==1) { disTime= temp +"" +getResources().getString(R.string.lbl_min_ago); } else { disTime = temp +"" +getResources().getString(R.string.lbl_mins_ago); } } else if(diff<(24*3600)) {// below 1 day // convert hr long temp= diff/3600; System.out.println("hey temp3:"+temp); if(temp==1) { disTime = temp +"" +getResources().getString(R.string.lbl_hr_ago); } else { disTime = temp +"" +getResources().getString(R.string.lbl_hrs_ago); } } else if(diff<(24*3600*7)) {// below week // convert days long temp=diff/(3600*24); if (temp==1) { // disTime ="\ yesterday"; disTime = temp +"" +getResources().getString(R.string.lbl_day_ago); } else { disTime = temp +"" +getResources().getString(R.string.lbl_days_ago); } } else if(diff<((24*3600*28))) {// below month // convert week long temp=diff/(3600*24*7); if (temp <= 4) { if (temp < 1) { disTime = getResources().getString(R.string.lbl_lstweek_ago); }else{ disTime = temp +"" + getResources().getString(R.string.lbl_week_ago); } } else { int diffMonth = mNow - m; Log.e("count :", String.valueOf(diffMonth)); disTime = diffMonth +"" + getResources().getString(R.string.lbl_month_ago); } }else if(diff<((24*3600*365))) {// below year // convert month long temp=diff/(3600*24*30); System.out.println("hey temp2:"+temp); if (temp <= 12) { if (temp == 1) { disTime = getResources().getString(R.string.lbl_onemonth_ago); }else{ disTime = temp +"" + getResources().getString(R.string.lbl_month_ago); } } }else if(diff>((24*3600*365))) { // above year // convert year long temp=diff/(3600*24*30*12); System.out.println("hey temp8:"+temp); if (temp == 1) { disTime = getResources().getString(R.string.lbl_oneyear_ago); }else{ disTime = temp +"" + getResources().getString(R.string.lbl_year_ago); } } } catch(Exception e) { e.printStackTrace(); } return disTime; } |
这是非常基本的脚本。它很容易即兴创作。
结果:(过去XXX小时)或(过去XX天/昨天/今天)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <span id='hourpost'></span> ,or <span id='daypost'></span> 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 ; |
这个对我有用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | 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; } } |
由于缺乏简洁性和更新的响应,请遵循最新的Java 8及更高版本
1 2 3 4 5 6 7 8 9 10 11 12 | import java.time.*; import java.time.temporal.*; public class Time { public static void main(String[] args) { System.out.println(LocalTime.now().minus(8, ChronoUnit.MINUTES)); System.out.println(LocalTime.now().minus(8, ChronoUnit.HOURS)); System.out.println(LocalDateTime.now().minus(8, ChronoUnit.DAYS)); System.out.println(LocalDateTime.now().minus(8, ChronoUnit.MONTHS)); } } |
该版本使用Java Time API尝试解决过去处理日期和时间的问题。
Java文档
版本8
https://docs.oracle.com/javase/8/docs/api/index.html?java/time/package-summary.html
版本11
https://docs.oracle.com/cn/java/javase/11/docs/api/java.base/java/time/package-summary.html
W3Schools教程-https://www.w3schools.com/java/java_date.asp
DZone文章-https://dzone.com/articles/java-8-date-and-time
我正在使用Instant,Date和DateTimeUtils。
数据(日期)以String类型存储在数据库中,然后转换为Instant。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | /* This method is to display ago. Example: 3 minutes ago. I already implement the latest which is including the Instant. Convert from String to Instant and then parse to Date. */ public String convertTimeToAgo(String dataDate) { //Initialize String conversionTime = null; String suffix ="Yang Lalu"; Date pastTime; //Parse from String (which is stored as Instant.now().toString() //And then convert to become Date Instant instant = Instant.parse(dataDate); pastTime = DateTimeUtils.toDate(instant); //Today date Date nowTime = new Date(); long dateDiff = nowTime.getTime() - pastTime.getTime(); long second = TimeUnit.MILLISECONDS.toSeconds(dateDiff); long minute = TimeUnit.MILLISECONDS.toMinutes(dateDiff); long hour = TimeUnit.MILLISECONDS.toHours(dateDiff); long day = TimeUnit.MILLISECONDS.toDays(dateDiff); if (second < 60) { conversionTime = second +" Saat" + suffix; } else if (minute < 60) { conversionTime = minute +" Minit" + suffix; } else if (hour < 24) { conversionTime = hour +" Jam" + suffix; } else if (day >= 7) { if (day > 30) { conversionTime = (day / 30) +" Bulan" + suffix; } else if (day > 360) { conversionTime = (day / 360) +" Tahun" + suffix; } else { conversionTime = (day / 7) +" Minggu" + suffix; } } else if (day < 7) { conversionTime = day +" Hari" + suffix; } return conversionTime; } |