使用Java静态方法中的“today”和“yesterday”字符串简化日期对象的替换

我有以下方法,我想更短或更快,如果没有别的。 欢迎所有评论:

Bellow方法接受一个日期对象,形成它(“EEE hh:mma MMM d,yyyy”),然后确定日期是今天还是昨天,如果是,则返回“(昨天|今天)hh:mma “格式化的字符串。

public static String formatToYesterdayOrToday(String date) { SimpleDateFormat sdf = new SimpleDateFormat("EEE hh:mma MMM d, yyyy"); Date in = null; try { in = sdf.parse(date); } catch (ParseException e) { log.debug("Date parsing error:", e); } Calendar x = Calendar.getInstance(); x.setTime(in); String hour = Integer.toString(x.get(Calendar.HOUR)); String minute = Integer.toString(x.get(Calendar.MINUTE)); String pm_am = x.get(Calendar.AM_PM) == Calendar.AM ? "AM" : "PM"; x.set(Calendar.HOUR, 0); x.set(Calendar.HOUR_OF_DAY, 0); x.set(Calendar.MINUTE, 0); x.set(Calendar.SECOND, 0); x.set(Calendar.MILLISECOND, 0); Calendar today = Calendar.getInstance(); today.set(Calendar.HOUR, 0); today.set(Calendar.HOUR_OF_DAY, 0); today.set(Calendar.MINUTE, 0); today.set(Calendar.SECOND, 0); today.set(Calendar.MILLISECOND, 0); Calendar yesterday = Calendar.getInstance(); yesterday.set(Calendar.HOUR, 0); yesterday.set(Calendar.HOUR_OF_DAY, 0); yesterday.set(Calendar.MINUTE, 0); yesterday.set(Calendar.SECOND, 0); yesterday.set(Calendar.MILLISECOND, 0); yesterday.add(Calendar.DATE, -1); if (x.compareTo(today) == 0) { return "Today " + hour + ":" + minute + pm_am; } if (x.compareTo(yesterday) == 0) { return "Yesterday " + hour + ":" + minute + pm_am; } return date; } 

以下是使用标准API改进的方法:

 public static String formatToYesterdayOrToday(String date) throws ParseException { Date dateTime = new SimpleDateFormat("EEE hh:mma MMM d, yyyy").parse(date); Calendar calendar = Calendar.getInstance(); calendar.setTime(dateTime); Calendar today = Calendar.getInstance(); Calendar yesterday = Calendar.getInstance(); yesterday.add(Calendar.DATE, -1); DateFormat timeFormatter = new SimpleDateFormat("hh:mma"); if (calendar.get(Calendar.YEAR) == today.get(Calendar.YEAR) && calendar.get(Calendar.DAY_OF_YEAR) == today.get(Calendar.DAY_OF_YEAR)) { return "Today " + timeFormatter.format(dateTime); } else if (calendar.get(Calendar.YEAR) == yesterday.get(Calendar.YEAR) && calendar.get(Calendar.DAY_OF_YEAR) == yesterday.get(Calendar.DAY_OF_YEAR)) { return "Yesterday " + timeFormatter.format(dateTime); } else { return date; } } 

以下是Jodatime如何做到这一点 :

 public static String formatToYesterdayOrToday(String date) { DateTime dateTime = DateTimeFormat.forPattern("EEE hh:mma MMM d, yyyy").parseDateTime(date); DateTime today = new DateTime(); DateTime yesterday = today.minusDays(1); DateTimeFormatter timeFormatter = DateTimeFormat.forPattern("hh:mma"); if (dateTime.toLocalDate().equals(today.toLocalDate())) { return "Today " + timeFormatter.print(dateTime); } else if (dateTime.toLocalDate().equals(yesterday.toLocalDate())) { return "Yesterday " + timeFormatter.print(dateTime); } else { return date; } } 

你写了“所有评论欢迎”所以这是我使用joda-time的方式。 🙂

我喜欢用iPhone最近的电话(类似谷歌浪潮post)以简短而聪明的方式显示日期和时间。 那是“hh:mm”如果今天, “昨天”或工作日的名称,如果<7天,否则yyyy-MM-dd

 private static boolean isToday (DateTime dateTime) { DateMidnight today = new DateMidnight(); return today.equals(dateTime.toDateMidnight()); } private static boolean isYesterday (DateTime dateTime) { DateMidnight yesterday = (new DateMidnight()).minusDays(1); return yesterday.equals(dateTime.toDateMidnight()); } private static String getDayString(Date date) { String s; if (isToday(new DateTime(date))) s = "Today"; else if (isYesterday(new DateTime(date))) s = "Yesterday"; else s = weekdayFormat.format(date); return s; } public static String getDateString_shortAndSmart(Date date) { String s; DateTime nowDT = new DateTime(); DateTime dateDT = new DateTime(date); int days = Days.daysBetween(dateDT, nowDT).getDays(); if (isToday(new DateTime(date))) s = getHourMinuteString(date); else if (days < 7) s = getDayString(date); else s = getDateString(date); return s; } 

我使用一组SimpleDateFormat(如上面的weekdayFormat)来格式化所需字符串的时间,以及DateTime和DateMidnight是joda-time类。

在这些情况下,两个DateTime:s之间经过的天数与人们定义谈论它的时间的相关性要小。 而不是计算几天(或我看到一些人做的毫秒)DateMidnight在这里很方便,但其他方法也可以。 🙂

使用java.util.Date.getTime()比较上面接受的答案之外的日期的另一种方法(注意:long应该用来代替int):

 Date today=new Date(); Date dateObj=null; long diff=0; try{ dateObj= formater1.parse(date); diff=(today.getTime()-dateObj.getTime())/(86400000); }catch(Exception e){} String days="TODAY"; if(diff==1){ days = "YESTERDAY"; }else if(diff>1){ days = String.valueOf(diff) + " " +"DAYS AGO"; } 

<%= days%>会返回:

今天

昨天

x DAYS AGO

我对这个问题的理解是提供一种生成输出的简单方法,如下所示:

 Today at 20:00 Today at 20:30 Today at 21:00 Tomorrow at 06:45 Tomorrow at 07:00 Tomorrow at 08:15 

下面的代码对我有用,但我是android的新手,也许其他人可能会指出代码是不健全的。 在’timeLong’下面的代码中是我在大纪元时间(毫秒)内的事件的时间。

 public String convertFromEpochTime (long timeLong) { long timeNow = System.currentTimeMillis(); // get day in relative time CharSequence timeDayRelative; timeDayRelative = DateUtils.getRelativeTimeSpanString(timeLong, timeNow, DateUtils.DAY_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE); // get hour in 24 hour time Format hourFormatter = new SimpleDateFormat("HH:mm"); String timeHour = hourFormatter.format(timeLong); // Log.d(DEBUG_TAG, "time of event: " + timeDayRelative + " at " + timeHour); String timeDayHour = timeDayRelative + " at "+ timeHour; return timeDayHour; } 

今天,昨天,明天

 String formatDate(String fecha){ String Rfecha=new String(); SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy"); //SimpleDateFormat formatter2 = new SimpleDateFormat("EEEE d MMM"); SimpleDateFormat formatter2 = new SimpleDateFormat("E, d MMM "); try { Date hoy=new Date(); Date date = formatter.parse(fecha); String pref=""; Log.d("hoy long", ""+(hoy.getTime()/ (1000*60*60*24))); Log.d("date long", ""+ (date.getTime()/ (1000*60*60*24))); int ihoy=(int) (hoy.getTime()/ (1000*60*60*24)); int idate=(int) (date.getTime()/ (1000*60*60*24)); int dif=idate-ihoy; if(dif==0) pref="Today"; if(dif==1) pref="Tomorrow"; if(dif==-1) pref="Yesterday"; Rfecha=pref+" "+formatter2.format(date); } catch (Exception e) { e.printStackTrace(); } return Rfecha; } 

看看jodatime: http ://joda-time.sourceforge.net/

这是来自doc的一些示例代码:

 public boolean isAfterPayDay(DateTime datetime) { if (datetime.getMonthOfYear() == 2) { // February is month 2!! return datetime.getDayOfMonth() > 26; } return datetime.getDayOfMonth() > 28; } public Days daysToNewYear(LocalDate fromDate) { LocalDate newYear = fromDate.plusYears(1).withDayOfYear(1); return Days.daysBetween(fromDate, newYear); } public boolean isRentalOverdue(DateTime datetimeRented) { Period rentalPeriod = new Period().withDays(2).withHours(12); return datetimeRented.plus(rentalPeriod).isBeforeNow(); } public String getBirthMonthText(LocalDate dateOfBirth) { return dateOfBirth.monthOfYear().getAsText(Locale.ENGLISH); } 

时区

问题和其他答案忽略了时区的关键问题。 该输入字符串缺少任何时区或从UTC偏移 。 因此,在假设它表示JVM当前默认时区中的日期时间时,将解析该字符串。 危险的业务(a)假设可能是错误的,(b)默认情况可能随时改变,即使运行时也是如此。

语言环境

问题和其他答案忽略了另一个关键问题: Locale 。 Locale确定用于在解析(和生成)期间从输入字符串转换日期名称和月份名称的人类语言。

如果未指定,则JVM的当前默认语言环境将用于转换。 与时区一样,JVM的默认Locale可以随时更改,即使运行时也是如此。

最好指定所需/期望的区域设置。

java.time

问题和其他答案使用旧的日期时间类,这些类已被certificate设计糟糕且麻烦。 Java 8及更高版本内置了java.time框架,其类取代了旧的。

在生成新字符串时解析字符串的方法应该分解为两种方法。 一种方法应解析以获取日期时间对象。 第二个应该采用日期时间对象并生成所需的字符串输出。 然后每个可以单独使用。 这种方法使我们不再将字符串视为日期时间值。 字符串是日期时间值的文本表示。 您的业​​务逻辑应该专注于将这些日期时间值作为对象进行操作,而不是关注字符串。

解析

 private ZonedDateTime parseLengthyString ( String input , ZoneId zoneId , Locale locale ) { // FIXME: Check for nulls. DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "EEE hh:mma MMM d, uuuu" ); formatter = formatter.withZone ( zoneId ); formatter = formatter.withLocale ( locale ); ZonedDateTime zdt = null; try { zdt = ZonedDateTime.parse ( input , formatter ); } catch ( DateTimeParseException e ) { // FIXME: handle exeption. System.out.println ( "ERROR - e: " + e ); } return zdt; // FIXME: Check for null. } 

发电

给定上述方法的ZonedDateTime ,我们可以使用指定的Locale生成日期时间值的文本表示,以翻译日期名称和月份名称。

为了确定日期时间是今天还是昨天,我们只关心日期部分而没有时间。 为此,我们可以在java.time中使用LocalDate类。

 private String generateLengthyString ( ZonedDateTime zdt , Locale locale ) { // FIXME: Check for nulls. // Compare the date-only value of incoming date-time to date-only of today and yesterday. LocalDate localDateIncoming = zdt.toLocalDate (); Instant instant = Instant.now (); ZonedDateTime now = ZonedDateTime.now ( zdt.getZone () ); // Get current date-time in same zone as incoming ZonedDateTime. LocalDate localDateToday = now.toLocalDate (); LocalDate localDateYesterday = localDateToday.minusDays ( 1 ); DateTimeFormatter formatter = null; if ( localDateIncoming.isEqual ( localDateToday ) ) { formatter = DateTimeFormatter.ofPattern ( "'Today' hh:mma" , locale ); // FIXME: Localize "Today". } else if ( localDateIncoming.isEqual ( localDateYesterday ) ) { formatter = DateTimeFormatter.ofPattern ( "'Yesterday' hh:mma" , locale ); // FIXME: Localize "Yesterday". } else { formatter = DateTimeFormatter.ofPattern ( "EEE hh:mma MMM d, uuuu" , locale ); } String output = zdt.format ( formatter ); return output; // FIXME: Check for null. } 

练习这两种方法。

任意选择America/New_York的时区作为问题未指定。

 String input = "Sat 11:23AM Feb 6, 2016"; ZoneId zoneId = ZoneId.of ( "America/New_York" ); Locale locale = Locale.US; ZonedDateTime zdt = this.parseLengthyString ( input , zoneId , locale ); String output = this.generateLengthyString ( zdt , locale ); 

顺便说一下,您可以要求java.time根据Locale的文化规范自动格式化输出字符串,而不是硬编码格式。

 String outputPerLocale = zdt.format ( DateTimeFormatter.ofLocalizedDateTime ( FormatStyle.MEDIUM ) ); 

转储到控制台。

 System.out.println ( "input: " + input + " | zdt: " + zdt + " | Instant: " + zdt.toInstant () + " | output: " | output + " + outputPerLocale: " + outputPerLocale ); 

输入:2016年2月6日星期六上午11:23 | zdt:2016-02-06T11:23-05:00 [America / New_York] | 即时:2016-02-06T16:23:00Z | 输出:今天上午11:23 | outputPerLocale:2016年2月6日上午11:23:00

顺便说一句,我建议在AMPM之前放置一个SPACE以便于阅读。

这是Balus c实施的扩展版。

试试这个,我使用joda-datatime2.2.jar和SimpleDateFormat实现它

 import java.text.SimpleDateFormat; import java.util.Date; import org.joda.time.DateMidnight; import org.joda.time.DateTime; import org.joda.time.Days; public class SmartDateTimeUtil { private static String getHourMinuteString(Date date){ SimpleDateFormat hourMinuteFormat = new SimpleDateFormat(" h:ma"); return hourMinuteFormat.format(date); } private static String getDateString(Date date){ SimpleDateFormat dateStringFormat = new SimpleDateFormat("EEE',' MMM d y',' h:ma"); return dateStringFormat.format(date); } private static boolean isToday (DateTime dateTime) { DateMidnight today = new DateMidnight(); return today.equals(dateTime.toDateMidnight()); } private static boolean isYesterday (DateTime dateTime) { DateMidnight yesterday = (new DateMidnight()).minusDays(1); return yesterday.equals(dateTime.toDateMidnight()); } private static boolean isTomorrow(DateTime dateTime){ DateMidnight tomorrow = (new DateMidnight()).plusDays(1); return tomorrow.equals(dateTime.toDateMidnight()); } private static String getDayString(Date date) { SimpleDateFormat weekdayFormat = new SimpleDateFormat("EEE',' h:ma"); String s; if (isToday(new DateTime(date))) s = "Today"; else if (isYesterday(new DateTime(date))) s = "Yesterday," + getHourMinuteString(date); else if(isTomorrow(new DateTime(date))) s = "Tomorrow," +getHourMinuteString(date); else s = weekdayFormat.format(date); return s; } public static String getDateString_shortAndSmart(Date date) { String s; DateTime nowDT = new DateTime(); DateTime dateDT = new DateTime(date); int days = Days.daysBetween(dateDT, nowDT).getDays(); if (isToday(new DateTime(date))) s = "Today,"+getHourMinuteString(date); else if (days < 7) s = getDayString(date); else s = getDateString(date); return s; } } 

使用和测试Util类的简单案例:

 import java.util.Calendar; import java.util.Date; public class SmartDateTimeUtilTest { public static void main(String[] args) { System.out.println("Date now:"+SmartDateTimeUtil.getDateString_shortAndSmart(new Date())); System.out.println("Date 5 days before :"+SmartDateTimeUtil.getDateString_shortAndSmart(getFutureDay(-5))); System.out.println("Date 1 day before :"+SmartDateTimeUtil.getDateString_shortAndSmart(getFutureDay(-1))); System.out.println("Date last month:"+SmartDateTimeUtil.getDateString_shortAndSmart(getFutureMonth(-1))); System.out.println("Date last year:"+SmartDateTimeUtil.getDateString_shortAndSmart(getFutureDate(-1))); System.out.println("Date 1 day after :"+SmartDateTimeUtil.getDateString_shortAndSmart(getFutureDay(1))); } public static Date getFutureDate(int numberOfYears){ Calendar c = Calendar.getInstance(); c.setTime(new Date()); c.add(Calendar.YEAR, numberOfYears); return c.getTime(); } public static Date getFutureMonth(int numberOfYears){ Calendar c = Calendar.getInstance(); c.setTime(new Date()); c.add(Calendar.MONTH, numberOfYears); return c.getTime(); } public static Date getFutureDay(int numberOfYears){ Calendar c = Calendar.getInstance(); c.setTime(new Date()); c.add(Calendar.DATE, numberOfYears); return c.getTime(); } } 

我知道我迟到了。 但我对这个问题有最短的解决方案。 如果你想根据日期显示“今天”或“昨天”,那么你只需要使用它

 String strDate = ""; if (DateUtils.isToday(date.getTime())) strDate = "Today"; else if (DateUtils.isToday(date.getTime() + DateUtils.DAY_IN_MILLIS)) strDate = "Yesterday"; 

这里变量日期是Date对象。