0

In Java I can get the first day of the month by this way:

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

I'm wondering if there a function to do that directly, because I can't find a function that grabs this vital information.

Something similar to what I'm trying to do here:

 for (int i = 1; i < days_in_month + first; i++) {
     // Some code
     if (i - first + 1 == date.get(Calendar.DAY_OF_MONTH)) {
         // Do something
     }
 }
Oleksandr Pyrohov
  • 14,685
  • 6
  • 61
  • 90
  • Why the first day of the month is an integer?? – Kenry Sanchez Jan 17 '18 at 20:19
  • 3
    To makes things clearer, you should explain what `date` variable is. It appears to be `Calendar` type, not a `Date` type. And mention whether you can use the newer `java.time` API or not, because if you can, you should. – Andreas Jan 17 '18 at 20:27
  • 2
    Just curious, why are you struggling with the old and long outdated `GregorianCalendar` class? `java.time`, the modern Java date and time API, is so much nicer to work with. On top of that, its `LocalDate` class makes your job simple: `originalLocalDate.withDayOfMonth(1).getDayOfWeek()`. – Ole V.V. Jan 18 '18 at 05:44
  • 1
    Another quite similar question: [Get first date of current month in java](https://stackoverflow.com/questions/14241836/get-first-date-of-current-month-in-java). Use your search engine to find still more. And next time please search before asking. – Ole V.V. Jan 18 '18 at 05:54
  • @OleV.V. I'm afraid that you didn't understand the question. –  Jan 18 '18 at 12:28
  • In that case, @Ibrahim, please explain again. I’m here to help. – Ole V.V. Jan 18 '18 at 18:16
  • This question is not a duplicate of any question asking how to do it using `java.time`. This is specifically asking if there is a way to do it automatically using `java.util` - it turns out there isn't. – corsiKa Jan 18 '18 at 19:55
  • @corsiKa True, check edit, maybe there is a way to do something similar with `java.time` but I think there will be a need for much (casting). –  Jan 18 '18 at 20:48
  • I understood that all the time. I consider it legitimate to suggest a different/better solution from the one asked for, it’s often helpful, either to the OP or to other readers, and you never know in advance whether it will be. I respect that you know best what is best on your situation. I will let my comments stand for other readers in other situations. – Ole V.V. Jan 18 '18 at 22:55
  • @Ibrahim Could you try to explain in plain words what you're looking to do? Not code? – corsiKa Jan 19 '18 at 03:10

3 Answers3

4

You can convert GregorianCalendar object to the LocalDate object and use it's convenient 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());
Oleksandr Pyrohov
  • 14,685
  • 6
  • 61
  • 90
  • 2
    `c.getTime().toInstant().atZone(ZoneId.systemDefault())` is a very long-winded way of saying `c.toZonedDateTime()`. – Andreas Jan 17 '18 at 20:57
1

Simply put, no. This is the correct way to get something like this.

This is literally the functionality they put in Java for making calculations like this possible. Any sort of "direct function" would simply do this internally (which I suggest you do.)

corsiKa
  • 81,495
  • 25
  • 153
  • 204
  • Pretty much short answer "NO". –  Jan 17 '18 at 20:27
  • Right. However, if possible, consider using the `java.time` package recommended by logger (before he deleted his answer... `someLocalDate.with(TemporalAdjusters.firstDayOfMonth())` might be better for you - but if you have to replace the entire date api in your app, it might not be worth it. – corsiKa Jan 17 '18 at 20:29
  • I'm preferring my current solution instead of the `java.time` API. Thanks. –  Jan 17 '18 at 20:35
  • 2
    Strictly speaking this answer is incorrect. The function is there, in `java.time`, even a couple of functions for obtaining the same. – Ole V.V. Jan 18 '18 at 06:02
  • @OleV.V. Strictly speaking, the function in `java.time` does not return a `Date` which is the class OP is using in his entire application, and this question is specifically tagged with. I also commented (2 above yours) that he should consider using `java.time` because it is superior, although probably not worth replacing his entire date layer for. But if the question asks for answers in `Date`, then answers in `java.time` are not correct (even if they are helpful.) My comment on logger's deleted answer (which with sufficient rep you could see) would make that clear. – corsiKa Jan 18 '18 at 15:13
  • 2
    Thanks for your comment, @corsiKa. I’m fine with different interpretations of the question. :-) Only the OP can tell what he meant. He has said already that he prefers his current (very hard to read IMHO) solution. The answers are here for future readers too. – Ole V.V. Jan 18 '18 at 15:24
  • As Ole V.V. commented, this Answer is technically incorrect. In Java 8, Java 9, and later, there are indeed built-in functions to get the day-of-week for the first of a month: `myGregCal.toZonedDateTime().toLocalDate().with( TemporalAdjusters.firstDayOfMonth() ).getDayOfWeek().getValue()` – Basil Bourque Jan 20 '18 at 07:31
  • @BasilBourque Again, no, that's still going to the `java.time` package - the fact that you can put 5 function calls chained together on one line is not the same as making a single function call. I'm well aware of `java.time` and have advocated its use in everywhere except the answer because the question is tagged specifically as javadate. – corsiKa Jan 20 '18 at 16:51
1

tl;dr

To get an integer number representing the day-of-week (1-7 for Monday-Sunday), for the first day of a moment’s year-month:

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.

… yields a number 1-7 for Monday-Sunday.

Tip: Better to skip the last step, and use DayOfWeek object instead of int:

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

java.time

The Answer by Oleksandr may be correct, and wins points for using the modern java.time classes rather than the legacy date-time classes. But there is a simpler take on such code. Also, the Question appears to want to go a step further, to get the day-of-week for the first-of-month.

Per the comment by Andreas, you could call GregorianCalendar::toZonedDateTime as a easy way to convert from the old legacy class GregorianCalendar to the modern ZonedDateTime class. The old classes gained new methods to facilitate converting between the legacy classes and the modern java.time classes.

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

From there extract a LocalDate object. The LocalDate class represents a date-only value without time-of-day and without time zone.

LocalDate ld = zdt.toLocalDate() ;

Adjust the value to the first day of the same month. Use a TemporalAdjuster implementation found in the TemporalAdjusters class.

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

Determine the day-of-week for that first-of-month date via a DayOfWeek enum object. That enum pre-defines 7 objects, one for each day of the week: MONDAY, TUESDAY, etc.

DayOfWeek dow = firstOfMonth.getDayOfWeek() ;

Consider using that DayOfWeek enum object instead of a mere clumsy int number to represent your day-of-week. Using objects rather than a int primitive makes your code more self-documenting, provides type-safety, and ensures valid values.

But if you insist, you may extract an int 1-7 for Monday-Sunday per the ISO 8601 standard.

int dowNumber = dow.getValue() ;

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, GregorianCalendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Good answer. I still think (and I know you agree) that one should prefer to avoid using `GregorianCalendar` in the first place if possible. – Ole V.V. Jan 20 '18 at 09:47