从任何给定的日期间隔返回一周的1到7天

时间:2016-02-09 15:36:48

标签: java date dictionary jodatime

我想从日期间隔返回日期地图:

  1. 从1到7天:

         From: "2016-02-09" to To: "2016-02-09" -> return : Tue
         From: "2016-02-09" to To: "2016-02-12" -> return : Tue, Wed, Thu, Fri
         From: "2016-02-02" to To: "2016-04-12" -> return : Tue, Wed, Thu, Fri, Sat, Sun, Mon (this should be sorted from Monday for the map)
    
  2. 使用returned day as key(字符串)和value always = true(布尔值)对已排序的地图(周从星期一开始)将重新用于其他目的。

  3. 我想使用joda-time 2.8.1,但我不知道如何处理日期间隔? 我设法得到了我想要的但只有一天:

    String input = "2016-02-09";
    DateTimeFormatter formatter = DateTimeFormat.forPattern( "yyyy-MM-dd" );
    LocalDate localDate = formatter.parseLocalDate( input );
    Locale locale = Locale.US;
    DateTimeFormatter formatterOutput = DateTimeFormat.forPattern( "E" ).withLocale( locale );
    String output = formatterOutput.print( localDate ); //Result = Tue
    

3 个答案:

答案 0 :(得分:4)

Joda-Time不支持(关闭)日历日期的间隔,而只支持时刻的间隔。所以这里有一个临时解决方法:

LocalDate start = LocalDate.parse("2016-02-09");
LocalDate end = LocalDate.parse("2016-02-12");
if (start.isAfter(end))  {
    return Collections.emptyMap();
}

LocalDate current = start;
Map<Integer, Boolean> map = new TreeMap<>();

do {
    map.put(current.getDayOfWeek(), Boolean.TRUE);
    current = current.plusDays(1);
} while (!current.isAfter(end) && map.size() < 7);

LocalDate ref = new LocalDate(2016, 2, 7); // sunday
DateTimeFormatter f = DateTimeFormat.forPattern("E").withLocale(Locale.US);
StringBuilder sb = new StringBuilder();

for (int dayOfWeek : map.keySet()) {
    String output = f.print(ref.plusDays(dayOfWeek));
    sb.append(", ");
    sb.append(output);
}
System.out.println(sb.delete(0, 2).insert(0, "[").append(']').toString());
// [Tue, Wed, Thu, Fri]
return map;

答案 1 :(得分:3)

首先,将你的想法转移到对象而不是字符串。字符串可能是您的最终输出,但将您的业务逻辑和数据保存在对象中。

java.time

本答案使用Java 8及更高版本中内置的java.time框架。

这些新课程的灵感来自Joda-Time,但是经过重新设计。由ThreeTenExtra项目扩展(其Interval类可能在这里有用)。

DayOfWeek

java.time框架包含DayOfWeek枚举。利用这些对象。换句话说,不要将字符串视为日期时间;字符串是日期时间值的文本表示。

您的问题的地图和列表部分令人困惑。不确定你想要的收藏品。但我会展示基本的想法。您可以将DayOfWeek个对象用作地图和列表中的键或值。

无需指定解析模式。您的字符串采用ISO 8601格式。在解析/生成字符串时,java.time类默认使用ISO 8601格式。

List< DayOfWeek > dows = new ArrayList<>();

LocalDate start = LocalDate.parse( "2016-02-09" );
LocalDate stop = LocalDate( "2016-02-12" );

添加一天循环。当我们到达停止日期时停止。这个&#34;半开&#34;方法通常用于日期时间工作,其中开头是包含性的,而结尾是独占的。例如,一周将被指定为从星期一开始并且一直运行但不包括下一个星期一。

LocalDate d = start;
while ( d.isBefore( stop ) ) {
    DayOfWeek dow = DayOfWeek.from ( d ); 
    dows.add( dow );
    d = d.plusDays( 1 );
}

Set

也许您正在寻找在一段时间内发生的星期值的明确列表。在这种情况下,请添加到Set而不是List。 Set省略重复。如果您希望以特定顺序显示结果,请使用SortedSet

输出本地化字符串

您可以生成一个字符串,其中每天的名称已本地化为人类语言,并缩写为文化规范。在要求DayOfWeek enum进行本地化时指定区域设置。

请注意,在某些语言(不是英语)中,一周中的某一天会有两种不同的拼写,具体取决于它是单独使用还是作为日期的一部分使用。 TextStyle枚举允许您指定。

String output = dow.getDisplayName( TextStyle.SHORT_STANDALONE , Locale.CANADA_FRENCH );  // Or Locale.US etc.

答案 2 :(得分:0)

更好的解决方案是仅检查开始日期和结束日期。它更好,因为你最多会有7次迭代:

    LocalDate start = LocalDate.parse("2016-02-09");
    LocalDate end = LocalDate.parse("2016-02-12");
    if (start.isAfter(end))  {
        return Collections.emptyMap();
    }
    Integer startDay = start.getDayOfWeek().getValue();
    Integer endDay = end.getDayOfWeek().getValue();
    if (startDay > endDay) {
        endDay += 7;
    }
    Map<DayOfWeek, Boolean> result = new LinkedHashMap<DayOfWeek, Boolean>();

    for (int i = startDay; i<=endDay; i++) {
        result.put(DayOfWeek.of(i), Boolean.TRUE);
    }