如图:
注意,评论时间戳的格式,刚才,几小时之前,几天之前.....
实现需要一个时间格式的工具类,如果用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(); } }