Java 格式化日期&;时间根据用户而定';s地区及;带秒的首选项

Java 格式化日期&;时间根据用户而定';s地区及;带秒的首选项,java,android,date,time,android-dateutils,Java,Android,Date,Time,Android Dateutils,我试图根据用户的设置获取格式化的日期(年、月、日期)和时间(小时、分钟、秒)字符串。Android开发者谷歌小组的帖子描述了我遇到的确切问题,但没有人帮助那个人解决它。我将总结如下: Android有这些类试图实现上述功能,但没有一个类同时使用用户偏好和显示秒数 java.text.DateFormat 不使用设置应用程序中设置的首选项 android.text.format.DateFormat 获取一个java.text.DateFormat对象,该对象使用getDateFormat()和g

我试图根据用户的设置获取格式化的日期(年、月、日期)和时间(小时、分钟、秒)字符串。Android开发者谷歌小组的帖子描述了我遇到的确切问题,但没有人帮助那个人解决它。我将总结如下:

Android有这些类试图实现上述功能,但没有一个类同时使用用户偏好和显示秒数

  • java.text.DateFormat
    不使用设置应用程序中设置的首选项

  • android.text.format.DateFormat
    获取一个
    java.text.DateFormat
    对象,该对象使用
    getDateFormat()
    getTimeFormat()
    正确格式化输出,但
    getTimeFormat()
    不包括秒

  • android.text.format.DateUtils
    不使用“设置”应用程序中显示日期的首选项集,也无法显示秒数

  • 例如,当设置中的首选项设置为DD/MM/YYYY且24小时格式=on时,运行以下代码:

    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中提供以下输出:

    2014年4月27日下午5:47:18
    27/04/2014 17:47
    2014年4月27日17:47
    
    “无”将提供所需的输出,使用上述首选项可以得到如下结果:

    27/04/2014 17:47:18
    
    我也查看了图书馆,但它似乎没有满足我的需要(如果我错了,请纠正我)


    TL;DR:在Android上,如何根据用户偏好设置日期/时间的格式,并使用秒数?

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

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

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

    tl;博士 2017年1月23日12:34:56

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

    时区对于确定日期至关重要。在任何一个特定的时刻,世界各地的日期都因地区而异。例如,中午夜后几分钟是新的一天,而中仍然是“昨天”

    大陆/地区
    的格式指定,例如,或
    太平洋/奥克兰
    。切勿使用3-4个字母的缩写,如
    EST
    IST
    ,因为它们不是真正的时区,也不是标准化的,甚至不是唯一的(!)

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

    DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu HH:mm:ss" ) ; 
    String output = zdt.format( f );
    
    2017年1月23日12:34:56


    关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&

    该项目现已启动,建议迁移到类

    要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是

    从哪里获得java.time类

    • ,及以后
      • 内置的
      • 标准JavaAPI的一部分,带有捆绑实现
      • Java9添加了一些次要功能和修复
      • 大部分java.time功能都在中向后移植到Java6和Java7
      • 该项目专门为Android采用了ThreeTen Backport(如上所述)

    乔达时间 更新:该项目现在在中,建议迁移到类

    以区域设置敏感的方式轻松格式化日期时间值。看看这个班

    用两个字母的顺序来获得你想要的格式。第一个字符是日期样式,第二个字符是时间样式。为短样式指定“S”,为中样式指定“M”,为长样式指定“L”,为全样式指定“F”。日期或时间可以通过指定样式字符“-”来输入

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

    如果不指定区域设置,JVM的当前默认区域设置将以静默方式应用。由于此默认设置可能会在运行之前或甚至在运行期间更改,因此我建议您指定所需/预期的区域设置。如果您确实希望使用当前默认值,我建议您也通过调用来指定它,以便使您的代码能够自文档化

    formatter = formatter.withLocale( Locale.CANADA_FRENCH );
    

    使用
    @我希望我能想出一个好的
    建议,我编写了以下代码,使用区域设置和用户设置格式化日期:

    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);
    }
    
    试试这个:

    long timestamp = System.currentTimeMillis();
    
    DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(getApplicationContext());
    DateFormat timeFormat = DateFormat.getTimeInstance();
    
    String currentTimeString =  dateFormat.format(timestamp) + " - " +            
           timeFormat.format(timestamp);
    

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

    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()
    。应用程序上下文不行。

    这是一个可行的解决方案。我将尝试这样做,尽管我有限的Java知识需要一些时间。如果有什么可用的,我会更新你。DateTimeFormat类是否使用Android用户设置?@plusCubed我不知道它在Android上是如何工作的。在真实的Java环境中,Joda Time
    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);
    }
    
    long timestamp = System.currentTimeMillis();
    
    DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(getApplicationContext());
    DateFormat timeFormat = DateFormat.getTimeInstance();
    
    String currentTimeString =  dateFormat.format(timestamp) + " - " +            
           timeFormat.format(timestamp);
    
    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;
    
    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";
      }
    }