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

问题描述 投票:8回答:9

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

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;
}
java date replace simplify
9个回答
40
投票

以下是使用标准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;
    }
}

3
投票

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

我喜欢用最近的iPhone(类似于Google wave帖子)以简短而聪明的方式显示日期和时间。那是“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在这里很方便,但其他方法也可以。 :)


2
投票

使用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


2
投票

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

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;
}

2
投票

Time Zone

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

Locale

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

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

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

java.time

问题和其他答案使用旧的日期时间类,这些类已被证明设计糟糕且麻烦。 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以便于阅读。


2
投票

今天,昨天,明天

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;
}

1
投票

看看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);
}

0
投票

这是Balusc实现的扩展版。

试试这个,我使用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:m a");
    return hourMinuteFormat.format(date);
}

private static String getDateString(Date date){
    SimpleDateFormat dateStringFormat = new SimpleDateFormat("EEE',' MMM d y',' h:m a");
    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:m a");
        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();
    }
}

0
投票

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

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

这里变量日期是Date对象。

© www.soinside.com 2019 - 2024. All rights reserved.