[英]Momentjs calendar() equivalent for Java
Momentjs has the calendar()
function to pretty print timespans like below. Momentjs具有
calendar()
函数,可以实现如下所示的打印时间跨度。
For example: 例如:
"Last Monday at 1:14 PM"
“上周一的1:14 PM”
"09/21/2017" (if the date is a while ago)
“ 09/21/2017”(如果日期是前一阵子)
Is there an equivalent function in Java (Joda-Time if possible)? Java中是否有等效的功能(如果可能,可以使用Joda-Time)?
moment().subtract(10, 'days').calendar(); // 09/21/2017
moment().subtract(6, 'days').calendar(); // Last Monday at 1:14 PM
moment().subtract(3, 'days').calendar(); // Last Thursday at 1:14 PM
moment().subtract(1, 'days').calendar(); // Yesterday at 1:14 PM
moment().calendar(); // Today at 1:14 PM
moment().add(1, 'days').calendar(); // Tomorrow at 1:14 PM
moment().add(3, 'days').calendar(); // Wednesday at 1:14 PM
moment().add(10, 'days').calendar(); // 10/11/2017
Modern approach uses the industry-leading java.time classes. 现代方法使用行业领先的java.time类。
ZoneId z = ZoneId.now( “America/Montreal” ) ;
LocalDate today = LocalDate.now( z ) ;
Use the plus and minus methods to do math. 使用加号和减号方法进行数学运算。
LocalDate tomorrow = today.plusDays( 1 ) ;
Search Stack Overflow. 搜索堆栈溢出。 Nearly every basic date-time Question has already been asked an answered.
几乎每个基本的日期时间问题都已经被要求回答。
The java.time classes do not generate strings such as “tomorrow” and “Last Monday”. java.time类不会生成诸如“明天”和“上周一”之类的字符串。 So no direct equivalent of your referenced library.
因此,没有直接等同于您引用的库的信息。 You will have to do the peasant work yourself.
您将不得不自己做农民工作。
Search for the DateTimeFormatter
class, and the DateTimeFormatterBuilder
class. 搜索
DateTimeFormatter
类和DateTimeFormatterBuilder
类。
Also, the DayOfWeek
enum and its auto-localizing getDisplayName
method may be useful. 同样,
DayOfWeek
枚举及其自动本地化的getDisplayName
方法可能很有用。
The prettytime library may help you, though I've not used it. 尽管我没有使用过prettytime库,但它可能会对您有所帮助。
The Joda-Time project is in maintenance mode. Joda-Time项目处于维护模式。 The team advises migration to the java.time classes.
该团队建议迁移到java.time类。
The java.time framework is built into Java 8 and later. java.time框架内置于Java 8及更高版本中。 These classes supplant the troublesome old legacy date-time classes such as
java.util.Date
, Calendar
, & SimpleDateFormat
. 这些类取代了麻烦的旧的旧式日期时间类,例如
java.util.Date
, Calendar
和SimpleDateFormat
。
The Joda-Time project, now in maintenance mode , advises migration to the java.time classes. 现在处于维护模式的Joda-Time项目建议迁移到java.time类。
To learn more, see the Oracle Tutorial . 要了解更多信息,请参见Oracle教程 。 And search Stack Overflow for many examples and explanations.
并在Stack Overflow中搜索许多示例和说明。 Specification is JSR 310 .
规格为JSR 310 。
Where to obtain the java.time classes? 在哪里获取java.time类?
The ThreeTen-Extra project extends java.time with additional classes. ThreeTen-Extra项目使用其他类扩展了java.time。 This project is a proving ground for possible future additions to java.time.
该项目为将来可能在java.time中添加内容提供了一个试验场。 You may find some useful classes here such as
Interval
, YearWeek
, YearQuarter
, and more . 您可以在这里找到一些有用的类,比如
Interval
, YearWeek
, YearQuarter
,和更多 。
There's no built-in function for that in Java, but it's not so hard to do it with the existing API's. Java中没有内置函数,但是使用现有的API并不是很难。 First you need to get the difference from today (in days), and choose the proper string based on moment.js rules :
首先,您需要获得与今天(以天为单位)的差额,然后根据moment.js规则选择适当的字符串:
Last week Last Monday at 2:30 AM
The day before Yesterday at 2:30 AM
The same day Today at 2:30 AM
The next day Tomorrow at 2:30 AM
The next week Sunday at 2:30 AM
Everything else 7/10/2011
In Joda-Time, you can use the org.joda.time.Days
class to get the difference in days. 在Joda-Time中,可以使用
org.joda.time.Days
类来获取天数差异。 One detail is that I'm considering just the date (day/month/year) and ignoring the time (hour/minute/second) to get the difference (but you can adjust it to your needs). 一个细节是,我只考虑日期(日/月/年),而忽略了时间(小时/分钟/秒)来获得差异(但您可以根据需要进行调整)。 The method will be like this:
该方法将是这样的:
public String calendar(DateTime dt) {
StringBuilder sb = new StringBuilder();
// check difference in days from today, considering just the date (ignoring the hours)
int days = Days.daysBetween(new LocalDate(), dt.toLocalDate()).getDays();
if (days == 0) { // today
sb.append("Today ");
} else if (days == 1) { // tomorrow
sb.append("Tomorrow ");
} else if (days == -1) { // yesterday
sb.append("Yesterday ");
} else if (days > 0 && days < 7) { // next week
sb.append(dt.dayOfWeek().getAsText(Locale.ENGLISH)).append(" ");
} else if (days < 0 && days > -7) { // last week
sb.append("Last ").append(dt.dayOfWeek().getAsText(Locale.ENGLISH)).append(" ");
}
if (Math.abs(days) < 7) { // difference is less than a week, append current time
sb.append("at ").append(dt.toString("h:mm a", Locale.ENGLISH));
} else { // more than a week of difference
sb.append(dt.toString("M/d/yyyy"));
}
return sb.toString();
}
I'm using a org.joda.time.LocalDate
to get the difference, so the time will be ignored (if you use a DateTime
instead, the difference is only 1 day if it has passed more than 24 hours, so change the code according to what you need). 我正在使用
org.joda.time.LocalDate
来获取时差,因此时间将被忽略(如果您使用DateTime
,则经过24小时以上的时差仅为1天,因此请更改代码根据您的需要)。
I also used Math.abs(days) < 7
to consider if the difference is more than a week, but I'm not sure if moment.js
considers <= 7
. 我还使用
Math.abs(days) < 7
来考虑差异是否超过一周,但是我不知道moment.js
认为<= 7
。
Anyway, some examples of usage: 无论如何,一些用法示例:
DateTime now = new DateTime();
System.out.println(calendar(now.minusDays(10))); // 9/22/2017
System.out.println(calendar(now.minusDays(6))); // Last Tuesday at 9:34 AM
System.out.println(calendar(now.minusDays(3))); // Last Friday at 9:34 AM
System.out.println(calendar(now.minusDays(1))); // Yesterday at 9:34 AM
System.out.println(calendar(now)); // Today at 9:34 AM
System.out.println(calendar(now.plusDays(1))); // Tomorrow at 9:34 AM
System.out.println(calendar(now.plusDays(3))); // Thursday at 9:34 AM
System.out.println(calendar(now.plusDays(10))); // 10/12/2017
The output is (considering that today is October 2 nd 2017, and I ran the code at 9:34 AM in my local time): 输出(考虑到今天是10月2日2017年第二 ,我跑的代码在我的本地时间上午09点34分):
9/22/2017
2017年9月22日
Last Tuesday at 9:34 AM上星期二上午9:34
Last Friday at 9:34 AM上周五上午9:34
Yesterday at 9:34 AM昨天上午9:34
Today at 9:34 AM今天上午9:34
Tomorrow at 9:34 AM明天上午9:34
Thursday at 9:34 AM星期四上午9:34
10/12/20172017年10月12日
You can also modify the method to take a reference date to compare with (instead of using a hardcoded new LocalDate()
inside the method). 您还可以修改该方法以获取一个参考日期进行比较(而不是在方法内部使用硬编码的
new LocalDate()
)。
Joda-Time is in maintainance mode and is being replaced by the new APIs, so I don't recommend start a new project with it. Joda-Time处于维护模式,并且已被新的API取代,因此,我不建议使用它来启动新项目。 Even in joda's website it says: "Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310)."
即使在joda的网站上,它也说: “请注意,Joda-Time被认为是一个很大的“完成”项目。没有计划进行重大增强。如果使用Java SE 8,请迁移到java.time(JSR-310)。” .
。
If you're using Java 8 , consider using the new java.time API . 如果您使用的是Java 8 ,请考虑使用新的java.time API 。 It's easier, less bugged and less error-prone than the old APIs .
与旧的API相比 ,它更容易, 更不会出错且更不会出错 。
If you're using Java 6 or 7 , you can use the ThreeTen Backport , a great backport for Java 8's new date/time classes. 如果您使用的是Java 6或7 ,则可以使用ThreeTen Backport ,它是Java 8的新日期/时间类的绝佳反向端口 。 And for Android , you'll also need the ThreeTenABP (more on how to use it here ).
对于Android ,您还需要ThreeTenABP (更多有关如何在此处使用它的信息 )。
The code below works for both. 下面的代码对两者都适用。 The only difference is the package names (in Java 8 is
java.time
and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp
), but the classes and methods names are the same. 唯一的区别是包名称(在Java 8中为
java.time
,在ThreeTen Backport(或Android的ThreeTenABP)中为org.threeten.bp
),但是类名和方法名相同。
This API is very similar to Joda-Time, so the code has minor differences: 该API与Joda-Time非常相似,因此代码之间存在细微差别:
static DateTimeFormatter HOUR_FORMAT = DateTimeFormatter.ofPattern("h:mm a", Locale.ENGLISH);
static DateTimeFormatter MDY_FORMAT = DateTimeFormatter.ofPattern("M/d/yyyy");
public String calendar(ZonedDateTime dt) {
StringBuilder sb = new StringBuilder();
// check difference in days from today, considering just the date (ignoring the hours)
long days = ChronoUnit.DAYS.between(LocalDate.now(), dt.toLocalDate());
if (days == 0) { // today
sb.append("Today ");
} else if (days == 1) { // tomorrow
sb.append("Tomorrow ");
} else if (days == -1) { // yesterday
sb.append("Yesterday ");
} else if (days > 0 && days < 7) { // next week
sb.append(dt.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH)).append(" ");
} else if (days < 0 && days > -7) { // last week
sb.append("Last ").append(dt.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH)).append(" ");
}
if (Math.abs(days) < 7) { // difference is less than a week, append current time
sb.append("at ").append(dt.format(HOUR_FORMAT));
} else { // more than a week of difference
sb.append(dt.format(MDY_FORMAT));
}
return sb.toString();
}
I used a ZonedDateTime
, which is an equivalent of Joda's DateTime
(it represents a date and time in a timezone). 我使用了
ZonedDateTime
, 它等效于Joda的DateTime
(它表示时区中的日期和时间)。
When calling DAYS.between
, I converted it to a LocalDate
, so the comparison considers only the date (day/month/year). 当调用
DAYS.between
,我将其转换为LocalDate
,因此比较仅考虑日期(日/月/年)。 If I used a ZonedDateTime
instead, the time would also be considered, so the result would be 1 day only if it has passed more than 24 hours (so you can change it according to your needs). 如果我改用
ZonedDateTime
,那么还将考虑时间,因此,只有经过24小时以上(因此您可以根据需要更改),结果才是1天。
Note that I also had to create 2 instances of DateTimeFormatter
. 请注意,我还必须创建2个
DateTimeFormatter
实例。 I created them outside of the method, so they can be reused (no need to create them all the time inside the method). 我在方法外部创建了它们,因此可以重用它们(无需始终在方法内部创建它们)。 Joda-Time didn't need it because the
toString
method in Joda's objects can take a pattern and internally creates a formatter, while in java.time
API you must create the formatter explicity. Joda-Time不需要它,因为Joda对象中的
toString
方法可以采用某种模式并在内部创建格式化程序,而在java.time
API中,您必须显式创建格式化程序。
Using it is also similar to Joda-Time: 使用它也类似于Joda-Time:
ZonedDateTime now = ZonedDateTime.now();
System.out.println(calendar(now.minusDays(10))); // 9/22/2017
System.out.println(calendar(now.minusDays(6))); // Last Tuesday at 9:34 AM
System.out.println(calendar(now.minusDays(3))); // Last Friday at 9:34 AM
System.out.println(calendar(now.minusDays(1))); // Yesterday at 9:34 AM
System.out.println(calendar(now)); // Today at 9:34 AM
System.out.println(calendar(now.plusDays(1))); // Tomorrow at 9:34 AM
System.out.println(calendar(now.plusDays(3))); // Thursday at 9:34 AM
System.out.println(calendar(now.plusDays(10))); // 10/12/2017
Just a note about timezones. 只是有关时区的注释。 In
java.time
API, all the date classes has a no-arg now()
method that gets the current date/time in the JVM's default timezone. 在
java.time
API中,所有日期类都有一个no-arg now()
方法,该方法获取JVM默认时区中的当前日期/时间。
Although it's very conveninent, it also has some drawbacks, because the default timezone can be changed without notice, even at runtime. 尽管它非常方便,但也有一些缺点,因为即使在运行时也可以在不通知的情况下更改默认时区。 It's better to specify which timezone you want, if possible.
如果可能的话,最好指定所需的时区。
The API uses IANA timezones names (always in the format Region/City
, like America/New_York
or Europe/Paris
). 该API使用IANA时区名称 (格式始终为
Region/City
,例如America/New_York
或Europe/Paris
)。 Avoid using the 3-letter abbreviations (like CET
or EST
) because they are ambiguous and not standard . 避免使用3个字母的缩写(例如
CET
或EST
),因为它们是模棱两可的并且不是标准的 。
You can get a list of available timezones (and choose the one that fits best your system) by calling ZoneId.getAvailableZoneIds()
. 您可以通过调用
ZoneId.getAvailableZoneIds()
获得可用时区的列表(并选择最适合您的系统的时区ZoneId.getAvailableZoneIds()
。
To get the current date/time in a specific timezone, use the ZoneId
class: 要获取特定时区中的当前日期/时间,请使用
ZoneId
类:
// get the current date/time in a specific timezone
ZonedDateTime.now(ZoneId.of("Europe/Paris"));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.