13

他に何もない場合でも、より短くまたはより速くしたい次の方法があります。すべてのコメントを歓迎します:

次のメソッドは、日付オブジェクトを受け取り、それをフォーマットして ("EEE hh:mma MMM d, yyyy")、日付が今日か昨日かを判断し、そうであれば "(Yesterday | Today) 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;
}
4

9 に答える 9

46

標準 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;
    }
}
于 2010-11-27T15:05:06.467 に答える
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 クラスです。

このような場合、2 つの DateTime:s の間の経過日数は、人々が時間を定義する方法よりも関連性が低くなります。ここでは、日数 (または一部の人が行っているようにミリ秒) を数える代わりに、DateMidnight が便利ですが、他の方法も同様に機能します。:)

于 2011-05-09T09:50:22.617 に答える
3

質問に対する私の理解は、次のような出力を生成する簡単な方法を提供することです。

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

以下のコードは私にとってはうまくいきましたが、私はアンドロイドが初めてで、コードが堅牢でない場合は他の人が指摘するかもしれません。以下のコードでは、「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;
}
于 2015-03-04T09:31:17.137 に答える
3

タイムゾーン

質問と他の回答は、タイムゾーンの重要な問題を無視しています。その入力文字列には、タイム ゾーンまたはoffset-from-UTCがありません。そのため、その文字列は、JVM の現在のデフォルト タイム ゾーンの日時を表していると想定して解析されます。(a) その仮定が間違っている可能性があること、および (b) そのデフォルトが実行時であってもいつでも変更される可能性があるため、危険なビジネス。

ロケール

質問とその他の回答では、別の重要な問題が無視されていますLocale。Locale は、解析 (および生成) 中に入力文字列から曜日名と月名を翻訳するために使用される人間の言語を決定します。

指定しない場合、JVM の現在のデフォルト ロケールが翻訳に使用されます。タイム ゾーンと同様に、JVM のデフォルト ロケールは、実行時であってもいつでも変更できます。

希望する/予想されるロケールを指定することをお勧めします。

java.time

質問とその他の回答では、設計が不十分で面倒であることが証明されている古い日時クラスを使用しています。Java 8 以降にはjava.timeフレームワークが組み込まれており、そのクラスは古いクラスに取って代わります。

新しい文字列を生成しながら文字列を解析する方法は、2 つの方法に分割する必要があります。1 つのメソッドは、日時オブジェクトを取得するために解析する必要があります。2 番目は日時オブジェクトを取り、目的の文字列出力を生成する必要があります。その後、それぞれを別々に使用できます。そして、このアプローチにより、文字列を日時値と考える必要がなくなります。文字列は、日時値のテキスト表現です。ビジネス ロジックは、文字列ではなく、これらの日時の値をオブジェクトとして操作することに重点を置く必要があります。

解析中

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 を使用して曜日名と月名を変換することで、その日時値のテキスト表現を生成できます。

日時が今日か昨日かを判断するには、時刻のない日付部分のみを考慮します。そのためにLocalDate、java.time のクラスを使用できます。

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

これらの 2 つの方法を実行します。

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 に依頼することができます。

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:23AM | zdt: 2016-02-06T11:23-05:00[アメリカ/ニューヨーク] | インスタント: 2016-02-06T16:23:00Z | 出力: 今日の午前 11 時 23 分 | outputPerLocale: 2016 年 2 月 6 日 11:23:00 AM

ちなみに、読みやすくするためにAMorの前に SPACE を入れることをお勧めします。PM

于 2016-02-06T22:00:07.053 に答える
1

jodatime を見てください: http://joda-time.sourceforge.net/

これはドキュメントのサンプルコードです:

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);
}
于 2010-11-27T15:06:43.927 に答える
0

私はこのパーティーに遅れていることを知っています。しかし、私はこの問題に対する最短の解決策を持っています。日付に基づいて「今日」または「昨日」を表示したい場合は、これを使用するだけです

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

ここで、変数 date はDateオブジェクトです。

于 2017-12-22T10:03:41.053 に答える
0

これは、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: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();
    }
}
于 2014-12-04T06:03:26.810 に答える