【问题标题】:DateUtils.formatDateRange() issues when formatting date range格式化日期范围时的 DateUtils.formatDateRange() 问题
【发布时间】:2016-06-16 02:33:47
【问题描述】:

在我的应用程序中,我从 Web 服务接收格式为 yyyy-MM-dd(例如 2016-03-05)的日期,我需要将它们格式化为 [abbreviated month] [date],例如Mar 5。此外,我有一个开始日期和结束日期,并希望将它们显示为一个日期范围,除非两个日期相同。

目前我正在使用DateUtils.formatDateRange(),它应该满足我的要求并提供适当的本地化,但我遇到了两个问题:

  1. 如果我的结束日期是开始日期的后一天,formatDateRange() 仅显示格式化的开始日期。例如,如果开始日期是 2016-03-05,结束日期为2016-03-06,该方法返回Mar 5(但它应该是Mar 5 - Mar 6)。为什么会这样?

  2. 当结束日期在同一个月时,月份不显示。例如,如果开始日期是 2016-03-05 并且结束日期是 2016-03-12,方法返回Mar 5 - 12。有没有办法让它显示Mar 5 - Mar 12

这是我的代码:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date startDate, endDate;
try {
    startDate = sdf.parse(startDateString);
    endDate = sdf.parse(endDateString);
} catch (ParseException ignored) {
    return null;
}

int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH;
return DateUtils.formatDateRange(context, startDate.getTime(), endDate.getTime(), flags);

【问题讨论】:

    标签: android date simpledateformat date-formatting android-dateutils


    【解决方案1】:

    在第一种情况下,日期格式化程序将您在范围内的结束日期视为 exclusive(而不是 inclusive 在该范围内)。如果您只是在结束日期上增加一毫秒,您将看到您期望的范围,因为现在日期范围包括结束日期的午夜时间点。

    在第二种情况下,恐怕您符合日期格式的当前区域设置规则。您几乎必须接受 Android 认为的最佳格式,或者为您想要支持的每个语言环境制定自己的规则。

    【讨论】:

      【解决方案2】:

      tl;博士

      LocalDate.parse( inputStart )
               .format( DateTimeFormatter.ofPattern( "MMM d" ).withLocale( Locale.US ) )
      + " - " + 
      LocalDate.parse( inputStop )
               .format( DateTimeFormatter.ofPattern( "MMM d" ).withLocale( Locale.US ) )
      

      3 月 5 日 - 3 月 6 日

      详情

      您可以非常简单地使用 java.time 类而不是麻烦的旧旧日期时间类(DateSimpleDateFormat)和外部库 DateUtils。

      您的输入日期字符串使用标准的ISO 8601 格式。 java.time 类在解析/生成字符串时默认使用标准格式。所以不需要指定格式模式。

      LocalDate 类表示没有时间和时区的仅日期值。

      LocalDate start = LocalDate.parse( "2017-01-23" );
      LocalDate stop = LocalDate.parse( "2017-02-14" );
      

      要生成仅包含缩写月份名称和日期的字符串,请使用DateTimeFormatter

      DateTimeFormatter f = DateTimeFormatter.ofPattern( "MMM d" );
      

      指定Locale 以确定 (a) 用于翻译日期名称、月份名称等的人类语言,以及 (b) 决定缩写、大写、标点符号、分隔符等问题的文化规范.

      f = f.withLocale( Locale.US ) ;  // Or Locale.CANADA_FRENCH, Locale.UK, Locale.ITALY, etc.
      

      要求LocalDate 生成一个表示其值的字符串。

      String output = start.format( f ) + " - " + stop.format( f ) ;
      

      1 月 23 日 - 2 月 14 日

      MonthDay

      如果您需要处理月份和日期的概念但没有年份,您可能会对 MonthDay 课程感兴趣。

      MonthDay md = MonthDay.of( 1 , 23 ) ;
      

      或者使用Month 枚举来指定月份参数。

      MonthDay start = MonthDay.of( Month.JANUARY , 23 ) ;
      MonthDay stop = MonthDay.of( Month.FEBRUARY , 14 ) ;
      

      要生成标准 ISO 8601 格式的字符串,请调用 toString

      String output = start.toString() ;
      

      --01-23

      或者使用上面看到的DateTimeFormatter

      String output = start.format( f );
      

      1 月 23 日

      ISO 8601 定义了一种使用斜线字符指示时间跨度的格式。因此,您相同的月日值范围将是:

      String output = start.toString() + "/" + stop.toString() ;
      

      --01-23/--02-14


      关于java.time

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

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

      要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

      从哪里获得 java.time 类?

      ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

      【讨论】:

        猜你喜欢
        • 2013-10-20
        • 2017-04-21
        • 2020-05-26
        • 1970-01-01
        • 1970-01-01
        • 2013-06-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多