如图:
注意,评论时间戳的格式,刚才,几小时之前,几天之前.....
实现需要一个时间格式的工具类,如果用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 blocke.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@Testpublic void givenCommentedUnder60SecondsAgo_thenFormatSaysJustNow() throws Exception {TimeStampFormatter formatter = new TimeStampFormatter();Date commentedAt = minusSeconds(59, now());String commentedAtFormatted = formatter.format(commentedAt);assertEquals("just now", commentedAtFormatted);}@Testpublic void givenCommented1MinuteAgo_thenFormatSays1MinuteAgo() throws Exception {TimeStampFormatter formatter = new TimeStampFormatter();Date commentedAt = minusMinutes(1, now());String commentedAtFormatted = formatter.format(commentedAt);assertEquals("1 minute ago", commentedAtFormatted);}@Testpublic 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);}@Testpublic void givenCommented1HourAgo_thenFormatSays1HourAgo() throws Exception {TimeStampFormatter formatter = new TimeStampFormatter();Date commentedAt = minusHours(1, now());String commentedAtFormatted = formatter.format(commentedAt);assertEquals("1 hour ago", commentedAtFormatted);}@Testpublic 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);}@Testpublic void givenCommented1DayAgo_thenFormatSays1DayAgo() throws Exception {TimeStampFormatter formatter = new TimeStampFormatter();Date commentedAt = minusDays(1, now());String commentedAtFormatted = formatter.format(commentedAt);assertEquals("1 day ago", commentedAtFormatted);}@Testpublic 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);}@Testpublic void givenCommented1WeekAgo_thenFormatSays1WeekAgo() throws Exception {TimeStampFormatter formatter = new TimeStampFormatter();Date commentedAt = minusWeeks(1, now());String commentedAtFormatted = formatter.format(commentedAt);assertEquals("1 week ago", commentedAtFormatted);}@Testpublic 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);}@Testpublic void givenCommented1MonthAgo_thenFormatSays1MonthAgo() throws Exception {TimeStampFormatter formatter = new TimeStampFormatter();Date commentedAt = minusMonths(1, now());String commentedAtFormatted = formatter.format(commentedAt);assertEquals("1 month ago", commentedAtFormatted);}@Testpublic 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);}@Testpublic void givenCommented1YearAgo_thenFormatSays1YearAgo() throws Exception {TimeStampFormatter formatter = new TimeStampFormatter();Date commentedAt = minusYears(1, now());String commentedAtFormatted = formatter.format(commentedAt);assertEquals("1 year ago", commentedAtFormatted);}@Testpublic 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();}
}