【问题标题】:Is there a function to provide the first day of the month?有提供每月第一天的功能吗?
【发布时间】:2018-01-17 20:17:06
【问题描述】:

在 Java 中,我可以通过这种方式获取每月的第一天:

GregorianCalendar date;
// Some code
int first = new GregorianCalendar(date.get(Calendar.YEAR),
            date.get(Calendar.MONTH), 1).get(Calendar.DAY_OF_WEEK);

我想知道是否有一个函数可以直接执行此操作,因为我找不到能够获取这些重要信息的函数。

类似于我在这里尝试做的事情:

 for (int i = 1; i < days_in_month + first; i++) {
     // Some code
     if (i - first + 1 == date.get(Calendar.DAY_OF_MONTH)) {
         // Do something
     }
 }

【问题讨论】:

  • 为什么一个月的第一天是整数??
  • 为了让事情更清楚,你应该解释一下date变量是什么。它似乎是 Calendar 类型,而不是 Date 类型。并提及您是否可以使用较新的java.time API,因为如果可以,您应该这样做。
  • 只是好奇,你为什么要在陈旧过时的GregorianCalendar类中挣扎? java.time,现代 Java 日期和时间 API,使用起来更方便。最重要的是,它的 LocalDate 类使您的工作变得简单:originalLocalDate.withDayOfMonth(1).getDayOfWeek()
  • 另一个非常相似的问题:Get first date of current month in java。使用您的搜索引擎找到更多。下次提问前请先搜索。
  • @OleV.V.恐怕你没听懂这个问题。

标签: java dayofweek date dayofmonth


【解决方案1】:

您可以将GregorianCalendar 对象转换为LocalDate 对象并使用它方便的API:

LocalDate getWithFirstDayOfMonth(GregorianCalendar c) {
    LocalDate date = c.toZonedDateTime().toLocalDate();
    return date.withDayOfMonth(1);
}

GregorianCalendar calendar = GregorianCalendar.from(ZonedDateTime.now());
LocalDate first = getWithFirstDayOfMonth(calendar);
System.out.println(first.getDayOfMonth());

【讨论】:

  • c.getTime().toInstant().atZone(ZoneId.systemDefault()) 是一种非常啰嗦的说法 c.toZonedDateTime()
【解决方案2】:

简单地说,不。这是获得这样的东西的正确方法。

这实际上是他们在 Java 中为使这样的计算成为可能而放入的功能。任何形式的“直接功能”都可以在内部完成(我建议你这样做。)

【讨论】:

  • 非常简短的回答“NO”。
  • 对。但是,如果可能,请考虑使用 logger 推荐的 java.time 包(在他删除他的答案之前...someLocalDate.with(TemporalAdjusters.firstDayOfMonth()) 可能对您更好 - 但如果您必须替换应用程序中的整个日期 api,它可能不会值得。
  • 我更喜欢我当前的解决方案,而不是 java.time API。谢谢。
  • 严格来说这个答案是不正确的。该函数在那里,在java.time 中,甚至有几个函数可以获得相同的。
  • 感谢您的评论,@corsiKa。我对这个问题有不同的解释很好。 :-) 只有 OP 才能说出他的意思。他已经说过他更喜欢他当前的(非常难以阅读恕我直言)解决方案。未来的读者也可以在这里找到答案。
【解决方案3】:

tl;博士

获取一个整数,表示一周中的某一天(1-7 表示周一至周日),表示某一时刻的年月的第一天:

myGregCal                                        // Avoid troublesome legacy date-time classes such as `GregorianCalendar`.
    .toZonedDateTime()                           // Convert from legacy class to modern java.time class, a `ZonedDateTime` object.
    .toLocalDate()                               // Extract a date-only object.        
    .with( TemporalAdjusters.firstDayOfMonth() ) // Adjust into first day of the same year-month.
    .getDayOfWeek()                              // Extract a `DayOfWeek` enum object for Monday, Tuesday, etc. Consider using this object directly rather than taking the next step to extract a `int` number.
    .getValue()                                  // Extract an `int` integer number, 1-7 for Monday-Sunday.

... 为周一至周日生成数字 1-7。

提示:最好跳过最后一步,并使用DayOfWeek 对象而不是int

myGregCal.toZonedDateTime().toLocalDate().with( TemporalAdjusters.firstDayOfMonth() ).getDayOfWeek()  // Render a `DayOfWeek` enum object.

java.time

Answer by Oleksandr 可能是正确的,并且因使用现代 java.time 类而不是旧的日期时间类而获得积分。但是对这样的代码有一个更简单的看法。此外,问题似乎想要更进一步,以获得第一个月的星期几。

根据 Andreas 的评论,您可以调用 GregorianCalendar::toZonedDateTime 作为从旧的遗留类 GregorianCalendar 转换为现代 ZonedDateTime 类的简单方法。旧类获得了新方法来促进旧类和现代 java.time 类之间的转换。

ZonedDateTime zdt = myGregCal.toZonedDateTime() ;  // Convert from legacy class to modern class.

从那里提取一个LocalDate 对象。 LocalDate 类表示没有时间和时区的仅日期值。

LocalDate ld = zdt.toLocalDate() ;

将该值调整为同月的第一天。使用 TemporalAdjusters 类中的 TemporalAdjuster 实现。

LocalDate firstOfMonth = ld.with( TemporalAdjusters.firstDayOfMonth() ) ;

通过DayOfWeek 枚举对象确定该月初日期的星期几。该枚举预定义了 7 个对象,一个用于一周中的每一天:MONDAYTUESDAY 等。

DayOfWeek dow = firstOfMonth.getDayOfWeek() ;

考虑使用 DayOfWeek 枚举对象而不是仅仅笨拙的 int 数字来表示您的星期几。使用对象而不是 int 原语可以使您的代码更具自记录性,提供类型安全性并确保有效值。

但如果您坚持,您可以根据ISO 8601 标准提取周一至周日的int 1-7。

int dowNumber = dow.getValue() ;

关于java.time

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

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

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

从哪里获得 java.time 类?

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

【讨论】:

  • 好答案。我仍然认为(我知道你同意)如果可能的话,人们应该首先避免使用GregorianCalendar
猜你喜欢
  • 2020-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-22
  • 1970-01-01
  • 2021-05-25
  • 1970-01-01
相关资源
最近更新 更多