代码之家  ›  专栏  ›  技术社区  ›  Nate

如何在java中确定通过周数和日数(周)的日期

  •  0
  • Nate  · 技术社区  · 7 年前

    我需要通过传递这些参数来获取日期

    1. 周数(一个月内),即1,2,3,4,5
    2. 日数(一周内)0(周日)至6(周六)

    我在 Calendar

    3 回复  |  直到 7 年前
        1
  •  2
  •   Anonymous    7 年前

    java.time 或JSR-310)超过了长期过时的 Calendar 还有朋友。现代类对程序员更友好,更易于使用,它们带来的惊喜更少,生成更清晰、更自然的代码(至少当你习惯了流畅的风格时),并且在出现错误时更容易调试。

    Hugo’s answer .

    我建议这种方法:

    public static LocalDate weekNoAndDayToDate(Year year, Month month, int weekOfMonth, int dayOfWeek) {
        // find day of week: convert from 0 (Sunday) to 6 (Saturday)
        // to DayOfWeek, from 1 (Monday) to 7 (Sunday)
        DayOfWeek dow;
        if (dayOfWeek == 0) { // Sunday
            dow = DayOfWeek.SUNDAY;
        } else {
            dow = DayOfWeek.of(dayOfWeek);
        }
        return year.atMonth(month)
                .atDay(1)
                .with(TemporalAdjusters.nextOrSame(dow))
                .with(ChronoField.ALIGNED_WEEK_OF_MONTH, weekOfMonth);
    }
    

        LocalDate today = weekNoAndDayToDate(Year.of(2017), Month.JULY, 1, 1);
    

    2017-07-03
    

    如果您需要 Date 或者 GregorianCalendar 例如,对于无法更改的旧API,请执行以下操作之一:

        Date oldfashiondDateObject
                = Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant());
        GregorianCalendar oldfashionedCalendarObject
                = GregorianCalendar.from(today.atStartOfDay(ZoneId.systemDefault()));
    

    日期

    Mon Jul 03 00:00:00 CEST 2017
    

    等于同一时间点。

        2
  •  1
  •   Jay Smith    7 年前

    根据年、周数和星期几使用创建日期 java.util.Calendar

    Calendar cal = Calendar.getInstance();
            cal.set(Calendar.YEAR, 2017);
            cal.set(Calendar.WEEK_OF_YEAR, 26);
            cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
    

    转换自 Calendar java.util.Date

    Date date = cal.getTime();
    

    转换的步骤 Date 进入 java.time.LocalDateTime

    LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    
        3
  •  1
  •   user7605325 user7605325    7 年前

    @Ole V.V. explained

    例如,ISO-8601标准考虑:

    • 第一周的最少天数:标准将第一周计算为至少需要4天

    月份分为多个时段,每个时段从定义的一周的第一天开始。同一个月的最早时间段称为周 0 如果少于最小天数和周数 1 如果它至少有最少的天数。

    根据您如何定义它们,您可以得到不同的结果。考虑2017年7月的日历:

         July 2017
    Su Mo Tu We Th Fr Sa
                       1
     2  3  4  5  6  7  8
     9 10 11 12 13 14 15
    16 17 18 19 20 21 22
    23 24 25 26 27 28 29
    30 31
    

    如果我们考虑ISO的定义,我们有:

    • 第0周-2017-07-01至2017-07.02
    • 第2周:2017-07-10至2017-07.16
    • 第4周:2017-07-23至2017-07.30
    • 第5周:2017-07-31

    • 第1周:2017-07-01
    • 第3周:2017-07-09至2017-07.15
    • 第4周:2017年7月16日至2017年07月21日
    • 第5周:2017年7月22日至2017年07月29日

    Calendar 已经发布了,我将使用新的API编写一个。如果您正在使用 ,考虑使用 new java.time API .这更容易, less bugged and less error-prone than the old APIs

    Java<=7. ,您可以使用 ThreeTen Backport ,是Java 8新的日期/时间类的一个很好的后台端口。对于 安卓 ,这是 ThreeTenABP here

    下面的代码适用于这两种情况。 唯一的区别是 包名称 (在Java 8中 java.time 在ThreeTen Backport(或Android的ThreeTenABP)中 org.threeten.bp ),但类和方法 都是一样的。

    我正在使用 DateTimeFormatter LocalDate (包含日/月/年字段)。我也在使用 WeekFields 类,可以将其配置为使用不同的周定义(第一天和第一周的最小天数)

    public LocalDate getDate(int weekOfMonth, int dayOfWeek, int month, int year) {
        // you can customize your week definition (first day of week and mininum days in first week)
        WeekFields wf = WeekFields.of(DayOfWeek.SUNDAY, 2);
        DateTimeFormatter fmt = new DateTimeFormatterBuilder()
            // week of month, using week definition from WeekFields
            .appendValue(wf.weekOfMonth()).appendPattern(" ")
            // day of week
            .appendValue(ChronoField.DAY_OF_WEEK)
            // month and year
            .appendPattern(" M/yyyy")
            // create formatter
            .toFormatter();
    
        return LocalDate.parse(weekOfMonth + " " +
               // Sunday is 0, adjusting value
               (dayOfWeek == 0 ? 7 : dayOfWeek) + " " + month + "/" + year, fmt);
    }
    

    使用此代码(一周从周日开始,需要将2天视为第一周-否则,如上面的第一个示例所示,一周将为零):

    LocalDate d = getDate(1, 6, 7, 2017);
    

    d 2017-07-08 (2017年7月1日星期六)。

    如果要使用ISO 8601定义,请使用常量 WeekFields.ISO 而不是使用 WeekFields.of() 方法


    @Ole V.V. suggested in the comments ,也可以在不创建格式化程序的情况下完成:获取第一个 dayOfWeek 并将其调整到所需的 weekOfMonth :

    public LocalDate getDate(int weekOfMonth, int dayOfWeek, int month, int year) {
        // you can customize your week definition (first day of week and mininum days in first week)
        WeekFields wf = WeekFields.of(DayOfWeek.SUNDAY, 2);
    
        // Sunday is 0, adjusting value
        DayOfWeek dow = DayOfWeek.of(dayOfWeek == 0 ? 7 : dayOfWeek);
    
        // get the first weekday of the month
        LocalDate first = LocalDate.of(year, month, 1).with(TemporalAdjusters.nextOrSame(dow));
    
        // check in which week this date is
        int week = first.get(wf.weekOfMonth());
    
        // adjust to weekOfMonth
        return first.plusWeeks(weekOfMonth - week);
    }
    


    PS: 日历 通过这些方法也具有类似的配置 setFirstDayOfWeek() setMinimalDaysInFirstWeek() get 方法。