Отображение времени назад, как в Twitter

Я использую DateUtils.getRelativeTimeSpanString() для отображения, когда сообщение сделано.

Строка, которую он возвращает, выглядит примерно так: 1 минута назад, но я хотел бы получить 1 минуту или 1 час и т. д. (сокращенно и без назад).

Я могу заменить «час» на «ч» или «минуту» на «м», но если язык отличается от английского, это не сработает. Это то, что Twitter сейчас использует. Английский/кириллица способ отображения Twitter.

введите здесь описание изображения

введите здесь описание изображения

ОБНОВЛЕНИЕ: я приму ответ от @Bradley Wilson, хотя добавлю сюда более чистое решение (снова используя пакет JodaTime). Также остальные ответы также могут быть изменены для получения того же результата, поэтому они заслуживают голосования. Спасибо вам всем:

    DateTime postMaded = new DateTime(your previous date);
    DateTime nowUpdate = new DateTime();

    Period period = new Period(postMaded, nowUpdate);

    PeriodFormatter formatter;

    Locale current = ConverterMethods.getCurrentLocale();

    if (current.getLanguage().contentEquals(any Cyrillic language )) {

        if (period.getYears() != 0) {
            formatter = new PeriodFormatterBuilder().appendYears().appendSuffix(" г.").printZeroNever().toFormatter();
        } else if (period.getMonths() != 0) {
            formatter = new PeriodFormatterBuilder().appendMonths().appendSuffix(" м").printZeroNever().toFormatter();
        } else if (period.getWeeks() != 0) {
            formatter = new PeriodFormatterBuilder().appendWeeks().appendSuffix(" седм.").printZeroNever().toFormatter();
        } else if (period.getDays() != 0) {
            formatter = new PeriodFormatterBuilder().appendDays().appendSuffix(" д").printZeroNever().toFormatter();
        } else if (period.getHours() != 0) {
            formatter = new PeriodFormatterBuilder().appendHours().appendSuffix(" ч").printZeroNever().toFormatter();
        } else if (period.getMinutes() != 0) {
            formatter = new PeriodFormatterBuilder().appendMinutes().appendSuffix(" мин").printZeroNever().toFormatter();
        } else {
            formatter = new PeriodFormatterBuilder().appendSeconds().appendSuffix(" с").printZeroNever().toFormatter();
        }

    } else {

        if (period.getYears() != 0) {
            formatter = new PeriodFormatterBuilder().appendYears().appendSuffix(" y").printZeroNever().toFormatter();
        } else if (period.getMonths() != 0) {
            formatter = new PeriodFormatterBuilder().appendMonths().appendSuffix(" mon").printZeroNever().toFormatter();
        } else if (period.getWeeks() != 0) {
            formatter = new PeriodFormatterBuilder().appendWeeks().appendSuffix(" w").printZeroNever().toFormatter();
        } else if (period.getDays() != 0) {
            formatter = new PeriodFormatterBuilder().appendDays().appendSuffix(" d").printZeroNever().toFormatter();
        } else if (period.getHours() != 0) {
            formatter = new PeriodFormatterBuilder().appendHours().appendSuffix(" h").printZeroNever().toFormatter();
        } else if (period.getMinutes() != 0) {
            formatter = new PeriodFormatterBuilder().appendMinutes().appendSuffix(" m").printZeroNever().toFormatter();
        } else {
            formatter = new PeriodFormatterBuilder().appendSeconds().appendSuffix(" s").printZeroNever().toFormatter();
        }
    }

person charbinary    schedule 06.01.2017    source источник
comment
Joda-Time (github.com/dlew/joda-time-android) имеет некоторые хорошие варианты для таких вещей.   -  person John O'Reilly    schedule 06.01.2017
comment
Было бы полезно указать пакеты, содержащие классы Period, PeriodFormatter, PeriodFormatterBuilder.   -  person RustamG    schedule 09.01.2017
comment
Я добавил это. Спасибо, что указали на это.   -  person charbinary    schedule 09.01.2017


Ответы (4)


Для этого вы можете использовать JodaTime:

Добавьте зависимость в файл уровня приложения Build.Gradle следующим образом:

compile 'net.danlew:android.joda:2.9.4.1'

и тогда вы можете просто реализовать эту функциональность.

private String time = "Just Now";

private String how_long_ago(String created_at) {
        DateTime sinceGraduation = new DateTime(created_at, GregorianChronology.getInstance());
        DateTime currentDate = new DateTime(); //current date

        Months diffInMonths = Months.monthsBetween(sinceGraduation, currentDate);
        Days diffInDays = Days.daysBetween(sinceGraduation, currentDate);
        Hours diffInHours = Hours.hoursBetween(sinceGraduation, currentDate);
        Minutes diffInMinutes = Minutes.minutesBetween(sinceGraduation, currentDate);
        Seconds seconds = Seconds.secondsBetween(sinceGraduation, currentDate);

        Log.d("since grad", "before if " + sinceGraduation);
        if (diffInDays.isGreaterThan(Days.days(31))) {
            time = diffInMonths.getMonths() + " months ago";
            if (diffInMonths.getMonths() == 1) {
                time = diffInMonths.getMonths() + " month ago";
            } else {
                time = diffInMonths.getMonths() + " months ago";
            }
            return time;
        } else if (diffInHours.isGreaterThan(Hours.hours(24))) {
            if (diffInDays.getDays() == 1) {
                time = diffInDays.getDays() + " day ago";
            } else {
                time = diffInDays.getDays() + " days ago";
            }
            return time;
        } else if (diffInMinutes.isGreaterThan(Minutes.minutes(60))) {
            if (diffInHours.getHours() == 1) {
                time = diffInHours.getHours() + " hour ago";
            } else {
                time = diffInHours.getHours() + " hours ago";
            }
            return time;
        } else if (seconds.isGreaterThan(Seconds.seconds(60))) {
            if (diffInMinutes.getMinutes() == 1) {
                time = diffInMinutes.getMinutes() + " minute ago";
            } else {
                time = diffInMinutes.getMinutes() + " minutes ago";
            }
            return time;
        } else if (seconds.isLessThan(Seconds.seconds(60))) {
            return time;
        }
        Log.d("since grad", "" + sinceGraduation);
        return time;
    }

Просто измените выход String на time, чтобы получить желаемый «1 м».

Примечание: вы можете использовать локализацию для изменения строки через свои ресурсы.

см. Руководство по локализации Android для получения более подробной информации.

person Bradley Wilson    schedule 06.01.2017

Взгляните на библиотеку PrettyTime.

Это довольно просто использовать:

import org.ocpsoft.prettytime.PrettyTime

PrettyTime p = new PrettyTime();
System.out.println(p.format(new Date()));
// prints "moments ago"

Вы также можете передать локаль для интернационализированных сообщений:

PrettyTime p = new PrettyTime(new Locale("fr"));
System.out.println(p.format(new Date()));
// prints "à l'instant"

Как отмечено в комментариях, Android имеет эту функцию, встроенную в android.text.format.DateUtils класс.

person Jaydip Umaretiya    schedule 06.01.2017
comment
Как я уже сказал, я использую DateUtils.getRelativeTimeSpanString(), он работает нормально. Но я хотел бы настроить вывод на каждом языке. Посмотреть изображения - person charbinary; 06.01.2017
comment
Это второй вариант: сначала попробуйте эту библиотеку PrettyTime. - person Jaydip Umaretiya; 06.01.2017
comment
Одна проблема: я не вижу способа реализовать сокращенный стиль, см. в качестве примера также этот ресурс. Похоже, что ОП очень хочет настраиваемой ширины текста, см. Также мой ответ. - person Meno Hochschild; 06.01.2017
comment
@ionicorn Это полезно для вас? - person Jaydip Umaretiya; 07.01.2017

вы можете использовать эту функцию, чтобы сделать это

  public static String getTimeAgo(long time) {
     if (time < 1000000000000L) {
     // if timestamp given in seconds, convert to millis
     time *= 1000;
  }

  long now = System.currentTimeMillis();
  if (time > now || time <= 0) {
     return null;
  }

  // TODO: localize
  final long diff = now - time;
  if (diff < MINUTE_MILLIS) {
     return "just now";
  } else if (diff < 2 * MINUTE_MILLIS) {
     return "a minute ago";
  } else if (diff < 50 * MINUTE_MILLIS) {
     return diff / MINUTE_MILLIS + " min ago";
  } else if (diff < 90 * MINUTE_MILLIS) {
     return "an hour ago";
  } else if (diff < 24 * HOUR_MILLIS) {
     return diff / HOUR_MILLIS + " hours ago";
  } else if (diff < 48 * HOUR_MILLIS) {
     return "yesterday";
  } else {
     return diff / DAY_MILLIS + " days ago";
  }
 }
person Amir_P    schedule 06.01.2017
comment
Нет, я не могу, потому что, если язык не английский, он не войдет ни в один из ваших случаев. Например, в кириллице минута/мин будет минута/мин. - person charbinary; 06.01.2017
comment
вы можете использовать строковые ресурсы для вашей локализации @ionicorn - person Amir_P; 06.01.2017

Использование моей библиотеки Time4A будет работать так, как вы указали в своем вопросе:

Печать относительного времени (со словом назад)

    PlainTimestamp now = PlainTimestamp.nowInSystemTime();
    PlainTimestamp earlier = now.minus(1, ClockUnit.MINUTES);
    Moment past = earlier.inStdTimezone();
    Locale russian = new Locale("ru");

    PrettyTime.of(Locale.ENGLISH).printRelativeInStdTimezone(past);
    // output: 1 minute ago

    PrettyTime.of(Locale.ENGLISH)
       .withShortStyle().printRelativeInStdTimezone(past);
    // output: 1 min. ago

    PrettyTime.of(russian).printRelativeInStdTimezone(past);
    // output: 1 минуту назад

    PrettyTime.of(russian).withShortStyle().printRelativeInStdTimezone(past);
    // output: 1 мин. назад

Печать фиксированного времени без слова назад

    IsoUnit days = CalendarUnit.DAYS;
    IsoUnit hours = ClockUnit.HOURS;
    IsoUnit minutes = ClockUnit.MINUTES;
    net.time4j.Duration<IsoUnit> d =
        Duration.in(Timezone.ofSystem(), days, hours, minutes)
            .between(earlier, now);

    PrettyTime.of(Locale.ENGLISH).print(d, TextWidth.WIDE);
    // output: 1 minute

    PrettyTime.of(Locale.ENGLISH).print(d, TextWidth.ABBREVIATED);
    // output: 1 min

    PrettyTime.of(Locale.ENGLISH).print(d, TextWidth.NARROW);
    // output: 1m

    PrettyTime.of(russian).print(d, TextWidth.WIDE);
    // output: 1 минута

    PrettyTime.of(russian).print(d, TextWidth.ABBREVIATED);
    // output: 1 мин

    PrettyTime.of(russian).print(d, TextWidth.NARROW);
    // output: 1 мин

Новейшая версия библиотеки использует данные CLDR-репозитория v30.0.2 (от Unicode-консорциума, фактически на 80 языках). При необходимости вы можете изменить текстовые ресурсы, определив свои собственные активы для распространения вместе с Time4A (затем переопределив активы по умолчанию).

person Meno Hochschild    schedule 06.01.2017