Get the last Monday of the month

I have a problem with the correct date of the last Monday of the previous month. I think that there is absolutely no correct calculation of it, as in this question and want to abandon arithmetic operations with constants. This code works as expected:

public class mCalendar {
  private int thisMonth;
  private int prevMonth;
  private int lstDayThisMonth;
  private int lstDayPrevMonth;
  private int weekOffset;
  private int LstMnd;
  public String monthLetter;
  Locale locale = Locale.getDefault();
  private Calendar mCal;

public mCalendar(){
  this.mCal = Calendar.getInstance();
  mCal.set(Calendar.MONTH,0);
  this.thisMonth = mCal.get(Calendar.MONTH);
  this.prevMonth = thisMonth - 1;
  this.lstDayThisMonth = mCal.getActualMaximum(Calendar.DAY_OF_MONTH);
  this.monthLetter = mCal.getDisplayName(Calendar.MONTH, Calendar.LONG, locale);

  mCal.set(Calendar.MONTH,prevMonth);
  this.lstDayPrevMonth = mCal.getActualMaximum(Calendar.DAY_OF_MONTH);
  mCal.set(Calendar.DAY_OF_MONTH,lstDayPrevMonth);
  this.LstMnd = mCal.get(Calendar.DAY_OF_WEEK_IN_MONTH);
  mCal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
  mCal.set(Calendar.DAY_OF_WEEK_IN_MONTH, LstMnd);
  this.weekOffset = mCal.get(Calendar.DAY_OF_MONTH);
}

      

But when I set Calendar.MONTH

to 1 in the second statement of the constructor body Calendar.DAY_OF_MONTH

, we return frist on Monday February. I expect the function will return me on Jan 26, but it will return on Feb 2. I think this is happening because February 1st is Sunday, but for example, for March, the code works correctly.

Help me please, i'm confused)

+3


source to share


2 answers


Why not use a library like Joda :



LocalDate lastDay = new LocalDate().minusMonths(1).dayOfMonth().withMaximumValue();
LocalDate lastMonday = lastDayOfMonth.dayOfWeek().withMinimumValue();

      

+2


source


TL; DR

date of the last Monday of the previous month

YearMonth.from(                                                // Represent entire month as a whole.
    LocalDate.now( ZoneId.of( "Africa/Tunis" ) )               // Determine today’s date for a particular time zone.
)
.minusMonths( 1 )                                              // Move to prior `YearMonth`.
.atEndOfMonth()                                                // Get the last day of that prior month as a `LocalDate`.
.with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) )  // Move to another date for a Monday, or remain if already on a Monday.

      

java.time

The modern approach uses java.time classes rather than the difficult old class Calendar

.

LocalDate

The class LocalDate

represents a date value only with no time and no time zone.

The time zone is critical for determining the date. At any given moment, the date changes around the world by zone. For example, a few minutes after midnight in Paris France is a new day, while it is still "yesterday" in Montreal Quebec .

If no time zone is specified, the JVM implicitly applies the current default time zone. This default can change at any time, so your results may vary. Better to specify the desired / expected timezone explicitly as an argument.

Specify the name of the time zone in the format continent/region

, for example America/Montreal

, Africa/Casablanca

or Pacific/Auckland

. Never use the 3-4 letter abbreviation, for example EST

or IST

, as they are not real time zones and not standardized and not even unique (!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

      

If you want to use the current JVMs timezone, ask for it and pass it as an argument. If this parameter is omitted, the default JVM is used implicitly. Better to be explicit.

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

      

Or enter a date. You can set the month to the number, with the normal number 1-12 for January-December.

LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ;  // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.

      

Or, better, use Month

predefined objects, one for each month of the year. Council. Use these objects Month

throughout your codebase, rather than just an integer, to make your code more self-documenting, provide valid values, and provide type safety .

LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;

      



Get the whole month with YearMonth

class.

YearMonth thisMonth = YearMonth.from( ld ) ;

      

Move to the previous month.

YearMonth priorMonth = thisMonth.minusMonths( 1 ) ;

      

Get the last day of this previous month.

LocalDate endOfPriorMonth = priorMonth.atEndOfMonth() ;

      

Get the previous Monday relative to the end of this previous month, unless the end of the month becomes Monday. Do this with the TemporalAdjuster

implementation found in TemporalAdjusters

.

LocalDate lastMondayOfPriorMonth = endOfPriorMonth.with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) ) ;

      


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the nasty old legacy date classes such as java.util.Date

, Calendar

and . SimpleDateFormat

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

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

Where can I get the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is proof of possible future additions to java.time. Here you can find useful classes, such as Interval

, YearWeek

, YearQuarter

and longer .

+1


source







All Articles