根据地区设置的日期和时间格式化

33

我对Java和Android开发都很新,所以这可能是一个愚蠢的问题,但我已经搜索了好几天,仍然找不到解决方法:

我尝试根据用户的语言环境输出java.util.Date

在StackOverflow上搜索导致我找到了这个:

java.util.Date date = new Date();
String dateString = DateFormat.getDateFormat(getApplicationContext()).format(date);

以下是输出结果:

20/02/2011
在我的法语本地化手机上。几乎没问题。 如何使用用户的语言环境来输出Date的小时、分钟和秒部分?我已经在android文档中查找,但没有找到任何信息。 非常感谢。
6个回答

34

9
很遗憾,这不包括第二份。 - lenooh

18

简而言之

ZonedDateTime                                   // Represent a moment as seen in the wall-clock time used by the people of a particular region (a time zone). 
.now( ZoneId.of( "Asia/Kolkata" ) )             // Capture the current moment as seen in the specified time zone. Returns a `ZonedDateTime` object.
.format(                                        // Generate text representing the value of this `ZonedDateTime` object.
    DateTimeFormatter                           // Class controlling the generation of text representing the value of a date-time object.
    .ofLocalizedDateTime ( FormatStyle.FULL )   // Automatically localize the string representing this date-time value.
    .withLocale ( Locale.FRENCH )               // Specify the human language and cultural norms used in localizing.
)                                               // Return a `String` object.

java.time

问题中的代码使用了麻烦的旧日期时间类,现在已经过时,被内置于Java 8及更高版本的java.time类所取代。

区域设置和时区之间没有任何关系。区域设置确定在生成表示日期时间值的字符串时使用的人类语言和文化规范。时区确定用于表示时间线上时刻的特定区域的挂钟时间

Instant类以UTC为基准,表示时间线上的某一时刻,分辨率为纳秒(最多可以有九个小数位)。

Instant instant = Instant.now();

2016-10-12T07:21:00.264Z

应用时区以获取一个 ZonedDateTime。我随意选择使用印度时区来展示此刻。同一时刻,时间线上的同一点。
ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = instant.atZone( z );

2016-10-12T12:51:00.264+05:30[Asia/Kolkata]

使用魁北克加拿大的区域设置生成一个字符串。让java.time自动本地化该字符串。
Locale l = Locale.CANADA_FRENCH;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime ( FormatStyle.FULL ).withLocale ( l );
String output = zdt.format ( f );  // Indian time zone with Québécois presentation/translation.

2016年10月12日星期三IST 12:51


关于 java.time

java.time 框架内置于 Java 8 及更高版本中。这些类替代了老旧的传统日期时间类,例如 java.util.Date.Calendarjava.text.SimpleDateFormat

Joda-Time 项目现在处于 维护模式,建议迁移到 java.time。

要了解更多信息,请查看Oracle教程。并在Stack Overflow上搜索许多示例和解释。规范是JSR 310

如何获取java.time类?

这个ThreeTen-Extra项目扩展了java.time的附加类。该项目是java.time可能未来添加的一些内容的试验场。您可以在此处找到一些有用的类,例如IntervalYearWeekYearQuarter更多

Diagram showing when to use java.time, ThreeTenABP, or Android desugaring API


你正在使用麻烦的旧日期时间类。嗯,公平地说,我确实在2011年提出了这个问题。不过还是谢谢你跟进回答。你可能需要编辑答案,以明确现在情况已经发生了变化。目前的回答似乎表明当时使用那些类是错误的,这可能会让人们感到困惑。 - ereOn
1
感谢您提供这篇写得非常好且结论明确的回复。 - Hank
@ereOn,我并没有任何批评的意图,也不会被任何读者所推断。所有帖子的日期都清楚地标明了,因此帖子的年龄是显而易见的,上下文也很清晰。事实上,我在第一句话中使用“现在”这个词就暗示了你的问题和我的回答之间的时间差。每个程序员都知道信息技术发展迅速,变化无常。 - Basil Bourque
没问题。我看到你编辑了问题,使语气不那么“学究”和个人化,这绝对更好。我很感激。很高兴我们都在这个过程中学到了一些东西。谢谢你的回答! - ereOn
这个Java SDK和大部分可用的API都只能在Android 26及以上版本上使用,这样的回答太糟糕了,而且还是从另一个与Android无关的问题中复制过来的。 - user924
显示剩余3条评论

9

java.text.DateFormat 拥有您可能需要的所有功能:

DateFormat.getDateInstance()

DateFormat.getTimeInstance()

但您需要的是:

DateFormat.getDateTimeInstance()。您还可以指定日期/时间部分的长度和区域设置。最终结果将是:

DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT, Locale.FRENCH).format(Date);

来源:http://docs.oracle.com/javase/7/docs/api/java/text/DateFormat.html


5

使用getBestDateTimePattern()

android.text.format包中的DateFormat.getBestDateTimePattern()会根据用户设置的语言环境创建最佳的日期和时间格式。

例如:骨架EEEE,MMM d,YYYY,jj:mm返回本地化的日期和时间如下所示。

Locale English (India):            Monday 9 Sep 2019, 9:33 PM
Locale English (United States):    Monday, Sep 9, 2019, 9:33 PM
Locale español (Estados Unidos):   lunes, 9 de sep. de 2019 9:33 PM
Locale español (México):           lunes, 9 de sep de 2019 21:33
Locale français (France):          lundi 9 sept. 2019 à 21:33
Locale português (Brasil):         segunda-feira, 9 de set de 2019 21:33

并且对于不同的区域设置也是如此。它还尊重区域设置的12小时或24小时时间格式。

如果要自定义您自己的骨架,请参考unicode.org上的UTS #35模式。

示例代码

以下是在Kotlin中测试的示例代码:

val skeleton = DateFormat.getBestDateTimePattern(Locale.getDefault(), "EEEE, MMM d, YYYY, jj:mm")
val formatter = SimpleDateFormat(skeleton, Locale.getDefault()).apply {
    timeZone = TimeZone.getDefault()
    applyLocalizedPattern(skeleton)
}
val dateTimeText = formatter.format(calendar.time)
Log.d("YourClass", "Locale ${Locale.getDefault().displayName}: $dateTimeText")

除了Calendar类,您还可以使用ZonedDateTime。只需将其转换为Date对象并将其提供给format()

例如:Date(zonedDateTime.toInstant().toEpochMilli())

希望这能帮到您。


3

DateFormat.getTimeInstance() 函数获取默认语言环境下默认格式的时间格式化器。你也可以传递一个样式和 Locale 参数。


1
public static String formatDate(Date date, boolean withTime)
{
    String result = "";
    DateFormat dateFormat;

    if (date != null)
    {
        try
        {
            String format = Settings.System.getString(context.getContentResolver(), Settings.System.DATE_FORMAT);
            if (TextUtils.isEmpty(format))
            {
                dateFormat = android.text.format.DateFormat.getDateFormat(context);
            }
            else
            {
                dateFormat = new SimpleDateFormat(format);
            }
            result = dateFormat.format(date);

            if (withTime)
            {
                dateFormat = android.text.format.DateFormat.getTimeFormat(context);
                result += " " + dateFormat.format(date);
            }
        }
        catch (Exception e)
        {
        }
    }

    return result;
}

5
看起来还可以,但是您不应该这样削弱例外情况。 - JoshDM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接