如图:
注意,评论时间戳的格式,刚才,几小时之前,几天之前.....
实现需要一个时间格式的工具类,如果用java.util.Date当然也可以实现,这里说的是更方便的joda-time。
maven地址:http://search.maven.org/#search%7Cga%7C1%7Cjoda-time
工具类如下:
package com.chunsheng.me.timestamp;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.Hours;
import org.joda.time.Minutes;
import org.joda.time.Months;
import org.joda.time.Weeks;
import org.joda.time.Years;
class TimeStampFormatter {
/**
* For use with java.util.Date
*/
public String format(Date timestamp) {
long millisFromNow = getMillisFromNow(timestamp);
long minutesFromNow = TimeUnit.MILLISECONDS.toMinutes(millisFromNow);
if (minutesFromNow < 1) {
return "just now";
}
long hoursFromNow = TimeUnit.MILLISECONDS.toHours(millisFromNow);
if (hoursFromNow < 1) {
return formatMinutes(minutesFromNow);
}
long daysFromNow = TimeUnit.MILLISECONDS.toDays(millisFromNow);
if (daysFromNow < 1) {
return formatHours(hoursFromNow);
}
long weeksFromNow = TimeUnit.MILLISECONDS.toDays(millisFromNow) / 7;
if (weeksFromNow < 1) {
return formatDays(daysFromNow);
}
long monthsFromNow = TimeUnit.MILLISECONDS.toDays(millisFromNow) / 30;
if (monthsFromNow < 1) {
return formatWeeks(weeksFromNow);
}
long yearsFromNow = TimeUnit.MILLISECONDS.toDays(millisFromNow) / 365;
if (yearsFromNow < 1) {
return formatMonths(monthsFromNow);
}
return formatYears(yearsFromNow);
}
private long getMillisFromNow(Date commentedAt) {
long commentedAtMillis = commentedAt.getTime();
long nowMillis = System.currentTimeMillis();
return nowMillis - commentedAtMillis;
}
/**
* For use with org.joda.DateTime
*/
public String format(DateTime commentedAt) {
DateTime now = DateTime.now();
Minutes minutesBetween = Minutes.minutesBetween(commentedAt, now);
if (minutesBetween.isLessThan(Minutes.ONE)) {
return "just now";
}
Hours hoursBetween = Hours.hoursBetween(commentedAt, now);
if (hoursBetween.isLessThan(Hours.ONE)) {
return formatMinutes(minutesBetween.getMinutes());
}
Days daysBetween = Days.daysBetween(commentedAt, now);
if (daysBetween.isLessThan(Days.ONE)) {
return formatHours(hoursBetween.getHours());
}
Weeks weeksBetween = Weeks.weeksBetween(commentedAt, now);
if (weeksBetween.isLessThan(Weeks.ONE)) {
return formatDays(daysBetween.getDays());
}
Months monthsBetween = Months.monthsBetween(commentedAt, now);
if (monthsBetween.isLessThan(Months.ONE)) {
return formatWeeks(weeksBetween.getWeeks());
}
Years yearsBetween = Years.yearsBetween(commentedAt, now);
if (yearsBetween.isLessThan(Years.ONE)) {
return formatMonths(monthsBetween.getMonths());
}
return formatYears(yearsBetween.getYears());
}
private String formatMinutes(long minutes) {
return format(minutes, " minute ago", " minutes ago");
}
private String formatHours(long hours) {
return format(hours, " hour ago", " hours ago");
}
private String formatDays(long days) {
return format(days, " day ago", " days ago");
}
private String formatWeeks(long weeks) {
return format(weeks, " week ago", " weeks ago");
}
private String formatMonths(long months) {
return format(months, " month ago", " months ago");
}
private String formatYears(long years) {
return format(years, " year ago", " years ago");
}
private String format(long hand, String singular, String plural) {
if (hand == 1) {
return hand + singular;
} else {
return hand + plural;
}
}
}
PS:
Date之常用:
private static Date date(String string) {
try {
return new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.UK).parse(string);
} catch (ParseException e) {
throw new IllegalArgumentException(e);
}
}
private static Date dateIso(String string){
try {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.getDefault());
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
return simpleDateFormat.parse(string);
} catch (ParseException e) {
throw new IllegalArgumentException(e);
}
}
dateIso("2014-02-14T18:40:50Z")
TimeStampFormatter t = new TimeStampFormatter();
//new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.UK).parse(string)
try {
System.out.println(t.format(new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.CHINA).parse("2016-02-14 09:00")));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
PS:Date实现:
import java.util.Date;
import java.util.concurrent.TimeUnit;
class TimeStampFormatter {
/**
* For use with java.util.Date
*/
public String format(Date timestamp) {
long millisFromNow = getMillisFromNow(timestamp);
long minutesFromNow = TimeUnit.MILLISECONDS.toMinutes(millisFromNow);
if (minutesFromNow < 1) {
return "just now";
}
long hoursFromNow = TimeUnit.MILLISECONDS.toHours(millisFromNow);
if (hoursFromNow < 1) {
return formatMinutes(minutesFromNow);
}
long daysFromNow = TimeUnit.MILLISECONDS.toDays(millisFromNow);
if (daysFromNow < 1) {
return formatHours(hoursFromNow);
}
long weeksFromNow = TimeUnit.MILLISECONDS.toDays(millisFromNow) / 7;
if (weeksFromNow < 1) {
return formatDays(daysFromNow);
}
long monthsFromNow = TimeUnit.MILLISECONDS.toDays(millisFromNow) / 30;
if (monthsFromNow < 1) {
return formatWeeks(weeksFromNow);
}
long yearsFromNow = TimeUnit.MILLISECONDS.toDays(millisFromNow) / 365;
if (yearsFromNow < 1) {
return formatMonths(monthsFromNow);
}
return formatYears(yearsFromNow);
}
private long getMillisFromNow(Date commentedAt) {
long commentedAtMillis = commentedAt.getTime();
long nowMillis = System.currentTimeMillis();
return nowMillis - commentedAtMillis;
}
private String formatMinutes(long minutes) {
return format(minutes, " minute ago", " minutes ago");
}
private String formatHours(long hours) {
return format(hours, " hour ago", " hours ago");
}
private String formatDays(long days) {
return format(days, " day ago", " days ago");
}
private String formatWeeks(long weeks) {
return format(weeks, " week ago", " weeks ago");
}
private String formatMonths(long months) {
return format(months, " month ago", " months ago");
}
private String formatYears(long years) {
return format(years, " year ago", " years ago");
}
private String format(long hand, String singular, String plural) {
if (hand == 1) {
return hand + singular;
} else {
return hand + plural;
}
}
}
from:http://blog.blundellapps.co.uk/creating-comments-with-timestamps-like-youtube/
import java.util.Date;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class JavaUtilDate_TimeStampFormatterTest {
private static final int DAYS_IN_A_WEEK = 7;
private static final int AVERAGE_DAYS_IN_A_MONTH = 30;
private static final int DAYS_IN_YEAR = 365; // We don't need the level of accuracy of leap years
@Test
public void givenCommentedUnder60SecondsAgo_thenFormatSaysJustNow() throws Exception {
TimeStampFormatter formatter = new TimeStampFormatter();
Date commentedAt = minusSeconds(59, now());
String commentedAtFormatted = formatter.format(commentedAt);
assertEquals("just now", commentedAtFormatted);
}
@Test
public void givenCommented1MinuteAgo_thenFormatSays1MinuteAgo() throws Exception {
TimeStampFormatter formatter = new TimeStampFormatter();
Date commentedAt = minusMinutes(1, now());
String commentedAtFormatted = formatter.format(commentedAt);
assertEquals("1 minute ago", commentedAtFormatted);
}
@Test
public void givenCommentedUnder60MinuteAgo_thenFormatSaysXMinutesAgo() throws Exception {
TimeStampFormatter formatter = new TimeStampFormatter();
Date commentedAt = minusMinutes(59, minusSeconds(59, now()));
String commentedAtFormatted = formatter.format(commentedAt);
assertEquals("59 minutes ago", commentedAtFormatted);
}
@Test
public void givenCommented1HourAgo_thenFormatSays1HourAgo() throws Exception {
TimeStampFormatter formatter = new TimeStampFormatter();
Date commentedAt = minusHours(1, now());
String commentedAtFormatted = formatter.format(commentedAt);
assertEquals("1 hour ago", commentedAtFormatted);
}
@Test
public void givenCommentedUnder24HoursAgo_thenFormatSaysXHoursAgo() throws Exception {
TimeStampFormatter formatter = new TimeStampFormatter();
Date commentedAt = minusHours(23, minusMinutes(59, now()));
String commentedAtFormatted = formatter.format(commentedAt);
assertEquals("23 hours ago", commentedAtFormatted);
}
@Test
public void givenCommented1DayAgo_thenFormatSays1DayAgo() throws Exception {
TimeStampFormatter formatter = new TimeStampFormatter();
Date commentedAt = minusDays(1, now());
String commentedAtFormatted = formatter.format(commentedAt);
assertEquals("1 day ago", commentedAtFormatted);
}
@Test
public void givenCommentedLessThan7DayAgo_thenFormatSaysXDaysAgo() throws Exception {
TimeStampFormatter formatter = new TimeStampFormatter();
Date commentedAt = minusDays(6, minusHours(23, minusMinutes(59, now())));
String commentedAtFormatted = formatter.format(commentedAt);
assertEquals("6 days ago", commentedAtFormatted);
}
@Test
public void givenCommented1WeekAgo_thenFormatSays1WeekAgo() throws Exception {
TimeStampFormatter formatter = new TimeStampFormatter();
Date commentedAt = minusWeeks(1, now());
String commentedAtFormatted = formatter.format(commentedAt);
assertEquals("1 week ago", commentedAtFormatted);
}
@Test
public void givenCommentedLessThan4WeeksAgo_thenFormatSaysXWeeksAgo() throws Exception {
TimeStampFormatter formatter = new TimeStampFormatter();
Date commentedAt = minusWeeks(3, minusDays(6, minusHours(23, minusMinutes(59, now()))));
String commentedAtFormatted = formatter.format(commentedAt);
assertEquals("3 weeks ago", commentedAtFormatted);
}
@Test
public void givenCommented1MonthAgo_thenFormatSays1MonthAgo() throws Exception {
TimeStampFormatter formatter = new TimeStampFormatter();
Date commentedAt = minusMonths(1, now());
String commentedAtFormatted = formatter.format(commentedAt);
assertEquals("1 month ago", commentedAtFormatted);
}
@Test
public void givenCommentedLessThan1YearAgo_thenFormatSaysXMonthsAgo() throws Exception {
TimeStampFormatter formatter = new TimeStampFormatter();
Date commentedAt = minusMonths(11, minusWeeks(3, minusDays(6, minusHours(23, minusMinutes(59, now())))));
String commentedAtFormatted = formatter.format(commentedAt);
assertEquals("11 months ago", commentedAtFormatted);
}
@Test
public void givenCommented1YearAgo_thenFormatSays1YearAgo() throws Exception {
TimeStampFormatter formatter = new TimeStampFormatter();
Date commentedAt = minusYears(1, now());
String commentedAtFormatted = formatter.format(commentedAt);
assertEquals("1 year ago", commentedAtFormatted);
}
@Test
public void givenCommentedOver1YearAgo_thenFormatSaysXYearsAgo() throws Exception {
TimeStampFormatter formatter = new TimeStampFormatter();
Date commentedAt = minusYears(2, minusMonths(11, minusWeeks(3, minusDays(6, minusHours(23, minusMinutes(59, now()))))));
String commentedAtFormatted = formatter.format(commentedAt);
assertEquals("2 years ago", commentedAtFormatted);
}
private Date minusSeconds(int seconds, Date date) {
return minus(date, TimeUnit.SECONDS.toMillis(seconds));
}
private Date minusMinutes(int minutes, Date date) {
return minus(date, TimeUnit.MINUTES.toMillis(minutes));
}
private Date minusHours(int hours, Date date) {
return minus(date, TimeUnit.HOURS.toMillis(hours));
}
private Date minusDays(int days, Date date) {
return minus(date, TimeUnit.DAYS.toMillis(days));
}
private Date minusWeeks(int weeks, Date date) {
return minus(date, TimeUnit.DAYS.toMillis(weeks * DAYS_IN_A_WEEK));
}
private Date minusMonths(int months, Date date) {
return minus(date, TimeUnit.DAYS.toMillis(months * AVERAGE_DAYS_IN_A_MONTH));
}
private Date minusYears(int years, Date date) {
return minus(date, TimeUnit.DAYS.toMillis(years * DAYS_IN_YEAR));
}
private Date minus(Date date, long minutesInMillis) {
date.setTime(date.getTime() - minutesInMillis);
return date;
}
private Date now() {
return new Date();
}
}