【问题标题】:Android - Displaying month name for different date formatsAndroid - 显示不同日期格式的月份名称
【发布时间】:2018-06-06 08:16:04
【问题描述】:

我有一个应用程序以本地化格式显示不同区域的日期和时间,也就是说 - 它根据用户的偏好显示日期和时间。但我的问题是它总是显示数字,即 yyyy.mm.dd,或 mm/dd/yyy,或 dd,mm,yyyy。我想要的是:显示日期以便日期是数字,年份是数字,但月份显示为字符串,即。 Jan / Xin / Gen / Jān / Yan... or 01 Jan 2018 / Jan 01 2018 / 2018 Jan 01,以此类推,但仍保持当前本地格式。我知道如果我像 MMM 一样对其进行硬编码,我可以做到这一点,但我希望它根据本地化格式进行更改。

所以基本上这是我的问题:如何根据从服务器获得的值(yyyy-MM-dd HH: mm: ss)显示本地化时间,月份显示为三字母词,无论它使用什么语言环境

我知道这个问题听起来很熟悉,但到目前为止,我已经尝试了很多答案,包括堆栈溢出和其他来源,但没有任何成功。我尝试过的一些事情包括:1/2/3/4/5/6 ...但我无法在我的示例中使用它。

我的适配器:

public void onBindViewHolder(RestaurantsAdapter.RestaurantsViewHolder holder, int position) {
    // getting restaurant data for the row
    Restaurant restaurant = restaurant Items.get(position);

    holder.userName.setText(restaurant .getUserName());
    holder.date.setText(convertDate(restaurant .getDateTime())); //string dobiti u formatu, pretvoriti ga u localized i podijeliti na dva dijela
    holder.time.setText(convertTime(restaurant .getDateTime()));

    TextDrawable.IBuilder builder = TextDrawable.builder()
            .beginConfig()
            .withBorder(0)
            .toUpperCase()
            .endConfig()
            .roundRect(10);
    ColorGenerator generator = ColorGenerator.MATERIAL;
    int color = generator.getColor(restaurant.getUserId());
    TextDrawable textDrawable = builder.build(restaurant Items.get(position).getUserName().substring(0, 1), color);
    holder.thumbNail.setImageDrawable(textDrawable);

    Picasso.with(context)
            .load(AppConfig.URL_PROFILE_PHOTO + restaurant.getThumbnailUrl())
            .placeholder(textDrawable)
            .error(textDrawable)
            .transform(new RoundedTransform(12, 0))
            .fit()
            .centerCrop()
            .into(holder.thumbNail);
}

 private String convertDate(String time) {
    final DateFormat shortDateFormat = android.text.format.DateFormat.getDateFormat(context.getApplicationContext());

    SimpleDateFormat dateFormatReceived = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
    SimpleDateFormat dateFormatConverted = new SimpleDateFormat(((SimpleDateFormat) shortDateFormat).toPattern(), Locale.getDefault());

    java.util.Date date = null;

    try {
        date = dateFormatReceived.parse(time);
    } catch (ParseException e) {
        e.printStackTrace();
    }

    return dateFormatConverted.format(date);
}

private String convertTime(String time) {
    final DateFormat shortTimeFormat = android.text.format.DateFormat.getTimeFormat(context.getApplicationContext());
    SimpleDateFormat timeFormatReceived = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
    SimpleDateFormat timeFormatConverted = new SimpleDateFormat(((SimpleDateFormat) shortTimeFormat).toPattern(), Locale.getDefault());

    java.util.Date date = null;

    try {
        date = timeFormatReceived.parse(time);
    } catch (ParseException e) {
        e.printStackTrace();
    }

    return timeFormatConverted.format(date);
}

更新:

我尝试将此添加到我的解决方案中:

 private String convertDate(String time) {
    final DateFormat shortDateFormat = android.text.format.DateFormat.getDateFormat(context.getApplicationContext());
    Calendar Now = Calendar.getInstance();
    Now.getDisplayName(Calendar.HOUR, Calendar.SHORT, Locale.getDefault());
    SimpleDateFormat dateFormatReceived = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
    SimpleDateFormat dateFormatConverted = new SimpleDateFormat(((SimpleDateFormat) shortDateFormat).toPattern(), Locale.getDefault());
    dateFormatConverted.getDisplayName(Calendar.HOUR, Calendar.SHORT, Locale.getDefault());
    java.util.Date date = null;

    try {
        date = dateFormatReceived.parse(time);
    } catch (ParseException e) {
        e.printStackTrace();
    }

    return dateFormatConverted.format(date);
}

【问题讨论】:

  • 您能否添加您获得日期/时间的格式以及您获得的输出?还有 MMM 格式不起作用的特定语言环境吗?另一方面,当您使用像 1970 年 1 月 1 日这样的日期格式时,我认为区域设置并不重要。如果日期是 11/12/17 会很重要,在这种情况下会造成混淆。
  • @LeoNeo 嘿 LeoNeo,这是我从服务器获得的格式:yyyy-MM-dd HH:mm:ss。我无法让它在几种不同的格式、3 个设备和 1 个模拟器上显示 :) 另外,我最初按你说的那样显示它,硬编码 2018 年 1 月 1 日,但我想让它更漂亮一点。
  • 请为了您自己的利益,停止使用早已过时且臭名昭著的麻烦SimpleDateFormat和朋友。即使在 Android 上,我也建议改用 JSR-310, AKA java.time, the modern Java date and time API。使用起来感觉好多了。

标签: java android datetime localization simpledateformat


【解决方案1】:

请尝试使用 getDisplayName(...) 方法

为了获得更多信息,您最好查看this 文档


已编辑

你可以尝试这种方式更充分:

int monthOfYear = Calendar.JULY; // 6
String monthName = new 
DateFormatSymbols(Locale.getDefault()).getShortMonths()[monthOfYear];

【讨论】:

  • 我已经尝试将它添加到我的代码中,如下所示:dateFormatConverted.getDisplayName(Calendar.HOUR, Calendar.SHORT, Locale.getDefault()); 但我收到一条消息,它无法解析方法 getDisplayName。
  • 请尝试使用方法 getDisplayName(..) 与 Calendar 类的实例。它会起作用:试试这样:Calendar Now = Calendar.getInstance(); Now.getDisplayName(Calendar.HOUR, Calendar.SHORT, Locale.getDefault());
  • 我已经尝试过了,但我仍然遇到同样的问题,它无法重新使用该方法。我已将我的编辑添加到上面更新的代码中
  • 我想我知道你的问题请使用其他库 `import java.util.Calendar;'我猜这是你的问题
  • 我从一开始就使用import java.util.Calendar;,但它无法正常工作
【解决方案2】:

我认为以下方法将为您提供所需的日期时间格式化程序。

public static DateTimeFormatter getLocalizedDateFormatter(Locale requestedLocale) {
    String formatPatternString = DateTimeFormatterBuilder.getLocalizedDateTimePattern(
            FormatStyle.SHORT, null, 
            Chronology.ofLocale(requestedLocale), requestedLocale);
    // if not already showing month name, modify so it shows abbreviated month name
    if (! formatPatternString.contains("MMM")) {
        formatPatternString = formatPatternString.replaceAll("M+", "MMM");
    }
    return DateTimeFormatter.ofPattern(formatPatternString, requestedLocale);
}

测试:

    Locale[] locales = { Locale.US, Locale.FRANCE, Locale.GERMANY,
            Locale.forLanguageTag("da-DK"), Locale.forLanguageTag("sr-BA") };
    LocalDate today = LocalDate.now(ZoneId.of("Europe/Sarajevo"));
    for (Locale currentLocale : locales) {
        DateTimeFormatter ldf = getLocalizedDateFormatter(currentLocale);
        System.out.format(currentLocale, "%-33S%s%n", 
                currentLocale.getDisplayName(), today.format(ldf));
    }

输出:

ENGLISH (UNITED STATES)          Dec/24/17
FRENCH (FRANCE)                  24/déc./17
GERMAN (GERMANY)                 24.Dez.17
DANSK (DANMARK)                  24-dec.-17
SERBIAN (BOSNIA AND HERZEGOVINA) 17-дец-24

JSR-310 也称为 java.time

您尝试使用过时且臭名昭著的麻烦类DateFormatSimpleDateFormat。相反,我建议您养成使用现代 Java 日期和时间 API JSR-310 的习惯。所以我在上面的方法中这样做了。

我认为这不是问题的一部分,但为了完整起见,请按如下方式解析日期时间字符串。您从我的getLocalizedDateFormatter 获得的格式化程序可用于格式化LocalDateTime 和除LocalDate 之外的许多其他日期时间类型。

    LocalDateTime ldt = LocalDateTime.parse("2017-12-24 22:51:34",
            DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss"));
    String formattedDate = ldt.format(getLocalizedDateFormatter(Locale.UK));

问题:我可以在 Android 上使用 JSR-310 吗?

是的,你可以。它只需要至少 Java 6

  • 在 Java 8 及更高版本中内置了新的 API。
  • 在 Java 6 和 7 中,获取 ThreeTen Backport,即新类的后向端口(JSR 310 的 ThreeTen)。
  • 在 Android 上,使用 ThreeTen Backport 的 Android 版本。它被称为 ThreeTenABP。

在后两种情况下,请确保将适当版本的 backport 库添加到您的项目中,使用下面的链接,并从 org.threeten.bporg.threeten.bp.format 导入我使用的类。

链接

【讨论】:

  • 今晚下班后我会看看这个,让你知道:) 感谢您的全面回答:)
  • 有个小问题,我的最小 API 是 17,它需要 26 才能工作。
  • 我不得不添加另一个评论,我已经问了很多问题,这是最好的,最全面的,包含的,多层次的(你甚至发现了 sr-BA,在波斯尼亚并没有真正使用,但日期有西里尔拼写:) ) 到目前为止我得到的答案。这也可能是我在堆栈溢出方面找到的最佳答案。正如我所说,我的小问题是 min API,但我不能接受任何其他答案:)
  • 我的错误是没有导入正确的类。它完美地工作。谢谢
  • 我一开始就没有解释清楚。谢谢@Kemo,指出我可以在其他时候做得更好。新年快乐。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多