格式化日期&根据用户的区域设置和时间几秒钟的偏好

时间:2014-04-28 02:02:50

标签: java android date time android-dateutils

我正在尝试根据用户的设置获取格式化日期(年,月,日)和时间(小时,分钟,秒)字符串。 Android开发者Google小组中的This帖子描述了我遇到的确切问题,但没有人帮助该人解决问题。我将总结一下:

Android有这些类尝试执行上述操作,但没有使用用户首选项并显示秒数。

  1. java.text.DateFormat中
    不使用在“设置”应用

  2. 中设置的偏好设置
  3. android.text.format.DateFormat
    获取java.text.DateFormat对象,使用getDateFormat()getTimeFormat()正确格式化输出,但getTimeFormat()不包含秒。

  4. android.text.format.DateUtils
    没有使用设置应用中显示日期的首选项,也无法显示秒数。

  5. 例如,如果设置中的首选项设置为DD / MM / YYYY且24小时格式=开启,则运行以下代码:

    long timestamp=System.currentTimeMillis();
    
    sometextview.setText(
        java.text.format.DateFormat.getDateTimeInstance().format(new Date(timestamp)) 
    
        +"\n"+ 
    
        android.text.format.DateFormat.getDateFormat(this).format(new Date(timestamp))
        +" "+
        android.text.format.DateFormat.getTimeFormat(this).format(new Date(timestamp))
    
        +"\n"+
    
        android.text.format.DateUtils.formatDateTime(this,
                                                     timestamp,    
                                                     DateUtils.FORMAT_SHOW_DATE| 
                                                     DateUtils.FORMAT_SHOW_TIME|
                                                     DateUtils.FORMAT_SHOW_YEAR)
    );
    

    在textview中给出了以下输出:

    Apr 27,2014 5:47:18 PM
    27/04/2014 17:47
    April 27,2014, 17:47
    

    None给出了所需的输出,使用上述首选项就是这样的:

    27/04/2014 17:47:18 
    

    我也查看了joda-time-android图书馆,但它似乎没有做我需要的事情(如果我错了,请纠正我。)

    TL; DR:如何根据Android上的用户偏好以秒格式化日期/时间?

5 个答案:

答案 0 :(得分:4)

使用@I wish I could think of a good的建议,我制作了以下代码,使用区域设置和用户设置格式化日期:

public static String timeDateStringFromTimestamp(Context applicationContext,long timestamp){
    String timeDate;
    String androidDateTime=android.text.format.DateFormat.getDateFormat(applicationContext).format(new Date(timestamp))+" "+
            android.text.format.DateFormat.getTimeFormat(applicationContext).format(new Date(timestamp));
    String javaDateTime = DateFormat.getDateTimeInstance().format(new Date(timestamp));
    String AmPm="";
    if(!Character.isDigit(androidDateTime.charAt(androidDateTime.length()-1))) {
        if(androidDateTime.contains(new SimpleDateFormat().getDateFormatSymbols().getAmPmStrings()[Calendar.AM])){
            AmPm=" "+new SimpleDateFormat().getDateFormatSymbols().getAmPmStrings()[Calendar.AM];
        }else{
            AmPm=" "+new SimpleDateFormat().getDateFormatSymbols().getAmPmStrings()[Calendar.PM];
        }
        androidDateTime=androidDateTime.replace(AmPm, "");
    }
    if(!Character.isDigit(javaDateTime.charAt(javaDateTime.length()-1))){
        javaDateTime=javaDateTime.replace(" "+new SimpleDateFormat().getDateFormatSymbols().getAmPmStrings()[Calendar.AM], "");
        javaDateTime=javaDateTime.replace(" "+new SimpleDateFormat().getDateFormatSymbols().getAmPmStrings()[Calendar.PM], "");
    }
    javaDateTime=javaDateTime.substring(javaDateTime.length()-3);
    timeDate=androidDateTime.concat(javaDateTime);
    return timeDate.concat(AmPm);
}

答案 1 :(得分:4)

试试这个:

long timestamp = System.currentTimeMillis();

DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(getApplicationContext());
DateFormat timeFormat = DateFormat.getTimeInstance();

String currentTimeString =  dateFormat.format(timestamp) + " - " +            
       timeFormat.format(timestamp);

答案 2 :(得分:3)

为什么不使用混合解决方案

android.text.format.DateFormat.getDateFormat(this).format(new Date(timestamp));

java.text.format.DateFormat.getDateTimeInstance().format(new Date(timestamp))

对于getDateTimeInstance将其另存为字符串并提取秒数,然后将其附加到getDateFormat

答案 3 :(得分:0)

TL;博士

ZonedDateTime.now( ZoneId.of( "America/Montreal" ) )
             .format( DateTimeFormatter.ofPattern( "dd/MM/uuuu HH:mm:ss" ) )
  

23/01/2017 12:34:56

java.time

添加ThreeTenABP项目(见下文)以访问java.time框架的现代日期时间类。旧的遗留日期时间类是出了名的麻烦,令人困惑和有缺陷。

时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因地区而异。例如,在Paris France午夜后的几分钟是新的一天,而Montréal Québec中仍然是“昨天”。

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTIST之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Montreal" );  // Or ZoneId.systemDefault()
ZonedDateTime zdt = ZonedDateTime.now( z );

使用DateTimeFormatter生成表示该ZonedDateTime对象值的字符串。指定自定义格式设置模式,或调用toLocalized…方法自动本地化为用户的人类语言和文化规范。

DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu HH:mm:ss" ) ; 
String output = zdt.format( f );
  

23/01/2017 12:34:56


关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?


约达时间

更新:现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

Joda-Time可以以区域设置敏感的方式轻松格式化日期时间值。查看DateTimeFormat类。

DateTimeFormatter formatter = DateTimeFormat.forStyle( "SM" );
DateTime dateTime = DateTime.now();
String output = formatter.print( dateTime );

使用这两个字母序列来获取您想要的格式。第一个字符是日期样式,第二个字符是时间样式。为短格式指定'S'字符,为中等指定'M',为长指定'L',为完整指定'F'。通过指定样式字符' - '可以省略日期或时间。

区域设置

Locale根据文化规范控制格式,并控制用于翻译日期名称,月份名称等的语言。

如果未指定Locale,则会以静默方式应用JVM的当前默认Locale。由于此默认值可能会在运行时之前或甚至在运行时期间发生更改,因此我建议您指定所需/预期的区域设置。如果您确实想要当前的默认值,我建议您同时调用Locale.getDefault,以便让您的代码自我记录。

formatter = formatter.withLocale( Locale.CANADA_FRENCH );

答案 4 :(得分:0)

有点黑客,但这似乎有效:

Date date = ...;
String dateStr = DateFormat.getLongDateFormat(context).format(date);
String timeStr;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
  String timeFormat = DateFormat.getBestDateTimePattern(Locale.getDefault(), DateFormat.is24HourFormat(context) ? "Hms" : "hmsa");
  timeStr = new SimpleDateFormat(timeFormat, Locale.getDefault()).format(date);
}
else {
  String timeFormat = DateFormat_getTimeFormatString(context).replace("mm", "mm:ss");
  timeStr = new SimpleDateFormat(timeFormat, Locale.getDefault()).format(date);
}
return dateStr + " " + timeStr;

它依赖于`DateFormat中的隐藏函数,我们可以通过反射使用

private static String DateFormat_getTimeFormatString(Context context) {
  try {
    final Method method = DateFormat.class.getDeclaredMethod("getTimeFormatString");
    method.setAccessible(true);
    return (String) method.invoke(context);
  }
  catch (Exception ignored) {
    return "HH:mm";
  }
}

从API 18开始,您可以使用新的getBestDateTimePattern()函数,该函数只需要显示您想要显示的数据列表,并返回最佳匹配模式。

如果查看is24HourFormat()源代码,它有点疯狂(它检查用户首选模式字符串中是否有大写的 H ),所以它可能值得如果您需要显示许多日期,请存储其值而不是重复调用它。

当然,您可以通过调用其他实例或使用DateUtils.formatDateTime()来确定日期所需的格式。

但是,有一个警告。确保使用活动上下文来询问is24HourFormat()。应用程序上下文不会这样做。

相关问题