jts*_*jts 122 java time datediff date relative-time-span
在Ruby on Rails中,有一个功能允许你采取任何日期并打印出"很久以前"的样子.
例如:
8 minutes ago
8 hours ago
8 days ago
8 months ago
8 years ago
Run Code Online (Sandbox Code Playgroud)
在Java中有一种简单的方法吗?
ata*_*lor 168
看看PrettyTime库.
它使用起来非常简单:
import org.ocpsoft.prettytime.PrettyTime;
PrettyTime p = new PrettyTime();
System.out.println(p.format(new Date()));
// prints "moments ago"
Run Code Online (Sandbox Code Playgroud)
您还可以传入国际化消息的区域设置:
PrettyTime p = new PrettyTime(new Locale("fr"));
System.out.println(p.format(new Date()));
// prints "à l'instant"
Run Code Online (Sandbox Code Playgroud)
正如评论中所述,Android具有内置于android.text.format.DateUtils该类中的此功能.
Ben*_*n J 66
你考虑过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();
}
Run Code Online (Sandbox Code Playgroud)
Ric*_*tta 47
我采用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));
}}
Run Code Online (Sandbox Code Playgroud)
这将打印以下内容
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
Run Code Online (Sandbox Code Playgroud)
Rea*_*wTo 42
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
*/
}
}
Run Code Online (Sandbox Code Playgroud)
这是基于RealHowTo的答案,所以如果你喜欢它,也要给他/她一些爱.
此清理版本允许您指定您可能感兴趣的时间范围.
它还处理"和"部分有点不同.我经常发现在使用分隔符连接字符串时,更容易跳过复杂的逻辑,并在完成后删除最后一个分隔符.
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();
}
}
Run Code Online (Sandbox Code Playgroud)
很少的代码让它旋转:
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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
这将输出以下内容:
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
Run Code Online (Sandbox Code Playgroud)
如果有人需要它,这里有一个类将上面的任何字符串转换回毫秒.它对于允许人们在可读文本中指定各种事物的超时非常有用.
小智 9
这有一个简单的方法:
假设您想要20分钟前的时间:
Long minutesAgo = new Long(20);
Date date = new Date();
Date dateIn_X_MinAgo = new Date (date.getTime() - minutesAgo*60*1000);
Run Code Online (Sandbox Code Playgroud)
而已..
Habsq 的答案的想法是正确的,但方法是错误的。
\n对于不依附于年-月-日时间线的时间跨度,请使用Period。对于表示与日历和小时-分钟-秒无关的 24 小时时间块的日期,请使用Duration。混合这两种规模几乎没有任何意义。
DurationInstant now = Instant.now(); // Capture the current moment as seen in UTC.\nInstant then = now.minus( 8L , ChronoUnit.HOURS ).minus( 8L , ChronoUnit.MINUTES ).minus( 8L , ChronoUnit.SECONDS );\nDuration d = Duration.between( then , now );\nRun Code Online (Sandbox Code Playgroud)\n生成小时、分钟和秒的文本。
\n// Generate text by calling `to\xe2\x80\xa6Part` methods.\nString output = d.toHoursPart() + " hours ago\\n" + d.toMinutesPart() + " minutes ago\\n" + d.toSecondsPart() + " seconds ago";\nRun Code Online (Sandbox Code Playgroud)\n转储到控制台。
\nSystem.out.println( "From: " + then + " to: " + now );\nSystem.out.println( output );\nRun Code Online (Sandbox Code Playgroud)\n\n\n从:2019-06-04T11:53:55.714965Z 到:2019-06-04T20:02:03.714965Z
\n
\n\n8 小时前
\n
\n\n8 分钟前
\n
\n\n8 秒前
\n
Period首先获取当前日期。
\n时区对于确定日期至关重要。对于任何特定时刻,全球各地的日期都会因地区而异。例如,法国巴黎午夜过后几分钟是新的一天,而Montr\xc3\xa9al Qu\xc3\xa9bec中仍然是 \xe2\x80\x9cyesterday\xe2\x80\x9d 。
\n如果未指定时区,JVM 会隐式应用其当前的默认时区。该默认值可能在运行时随时更改(!),因此您的结果可能会有所不同。最好明确指定您想要/预期的时区作为参数。如果重要,请与您的用户确认该区域。
\n以、、 或 等格式指定正确的时区名称。切勿使用 2-4 个字母的缩写,例如或,因为它们不是真实时区,不是标准化的,甚至不是唯一的(!)。Continent/RegionAmerica/MontrealAfrica/CasablancaPacific/AucklandESTIST
ZoneId z = ZoneId.of( "America/Montreal" ) ; \nLocalDate today = LocalDate.now( z ) ;\nRun Code Online (Sandbox Code Playgroud)\n重新创建八天、八月和几年前的日期。
\nLocalDate then = today.minusYears( 8 ).minusMonths( 8 ).minusDays( 7 ); // Notice the 7 days, not 8, because of granularity of months. \nRun Code Online (Sandbox Code Playgroud)\n计算经过的时间。
\nPeriod p = Period.between( then , today );\nRun Code Online (Sandbox Code Playgroud)\n拼搭一串“很久以前”的作品。
\nString output = p.getDays() + " days ago\\n" + p.getMonths() + " months ago\\n" + p.getYears() + " years ago";\nRun Code Online (Sandbox Code Playgroud)\n转储到控制台。
\nSystem.out.println( "From: " + then + " to: " + today );\nSystem.out.println( output );\nRun Code Online (Sandbox Code Playgroud)\n\n\n从: 2010-09-27 到: 2019-06-04
\n
\n\n8 天前
\n
\n\n8个月前
\n
\n\n8年前
\n
java.time框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat。
要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
\nJoda -Time项目现在处于维护模式,建议迁移到java.time类。
\n您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC 驱动程序。不需要字符串,不需要类。java.sql.*
从哪里获取 java.time 类?
\nThreeTen -Extra项目通过附加类扩展了 java.time。该项目是 java.time 未来可能添加的内容的试验场。您可能会在这里找到一些有用的类,例如Interval、、、等等。YearWeekYearQuarter
基于这里的一堆答案,我为我的用例创建了以下内容。
用法示例:
String relativeDate = String.valueOf(
TimeUtils.getRelativeTime( 1000L * myTimeInMillis() ));
Run Code Online (Sandbox Code Playgroud)
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();
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
如果你想找一个简单的"今天","昨天"或"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";
}
Run Code Online (Sandbox Code Playgroud)
使用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");
Run Code Online (Sandbox Code Playgroud)
关于内置解决方案:
Java没有任何内置支持格式化相对时间,也没有Java-8及其新包java.time.如果你只需要英语而不需要其他任何东西,那么只有手工制作的解决方案才可以接受 - 请参阅@RealHowTo的答案(尽管它有一个很大的缺点,就是不考虑将即时增量转换为当地时间的时区单位!).无论如何,如果你想避免本土复杂的解决方法,特别是对于其他语言环境,那么你需要一个外部库.
在后一种情况下,我建议使用我的库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)
Run Code Online (Sandbox Code Playgroud)
另一个使用java.time.Instant输入的例子:
String relativeTime =
PrettyTime.of(Locale.ENGLISH)
.printRelativeInStdTimezone(Moment.from(Instant.EPOCH));
System.out.println(relativeTime); // 45 years ago
Run Code Online (Sandbox Code Playgroud)
该库通过其最新版本(v4.17)支持80种语言以及一些特定国家/地区的语言环境(特别是西班牙语,英语,阿拉伯语,法语).i18n数据主要基于最新的CLDR版本v29.使用此库的其他重要原因是对多个规则(通常与其他语言环境中的英语不同),缩写格式样式(例如:"1秒前")以及考虑时区的表达方式的良好支持.Time4J甚至意识到这些奇特的细节,比如计算相对时间的闰秒(不是很重要,但它形成了与期望视野相关的信息).与Java-8的兼容性由于类似java.time.Instant或类型的容易获得的转换方法而存在java.time.Period.
有什么缺点吗?只有两个.
(紧凑型)替代品:
如果您寻找更小的解决方案并且不需要这么多功能并且愿意容忍与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数据的未经证实的贡献.
public static String getTimeAgoFormat(long timestamp) {
return android.text.format.DateUtils.getRelativeTimeSpanString(timestamp).toString();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
85943 次 |
| 最近记录: |