获取上个星期一的月份

时间:2015-05-27 19:05:43

标签: java date calendar

我在获取上个星期一的正确日期时遇到问题。 我认为在this问题中计算它并不是绝对正确的 并希望拒绝使用常量的算术运算。 此代码按预期工作:

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);
}

但是当我在构造函数体Calendar.MONTH的第二条指令中将Calendar.DAY_OF_MONTH设置为1时,返回2月的星期一。我希望函数在1月26日返回给我,但它会在2月2日返回。我认为这是因为2月1日它是星期日,但是,例如,3月代码工作正常。

请帮帮我,我很困惑)

2 个答案:

答案 0 :(得分:2)

为什么不使用像Joda这样的库:

a.h

答案 1 :(得分:1)

TL;博士

  

上个月的上个星期一的日期

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

现代方法使用 java.time 类而不是麻烦的旧Calendar类。

LocalDate

LocalDate类表示没有时间且没有时区的仅限日期的值。

时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因地区而异。例如,在Paris France午夜后的几分钟是新的一天,而Montréal Québec中仍然是“昨天”。

如果未指定时区,则JVM会隐式应用其当前的默认时区。该默认值可能随时更改,因此您的结果可能会有所不同。最好明确指定您期望/预期的时区作为参数。

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTIST之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

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

如果要使用JVM的当前默认时区,请求它并作为参数传递。如果省略,则隐式应用JVM的当前默认值。最好是明确的。

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

或指定日期。您可以将月份设置为一个数字,1月至12月的数字为1-12。

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.

或者,更好的是,使用预定义的Month枚举对象,一年中的每个月一个。提示:在整个代码库中使用这些Month对象,而不仅仅是整数,以使代码更具自我记录功能,确保有效值,并提供type-safety

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

使用YearMonth课程获得整个月份。

YearMonth thisMonth = YearMonth.from( ld ) ;

移至上个月。

YearMonth priorMonth = thisMonth.minusMonths( 1 ) ;

获取上个月的最后一天。

LocalDate endOfPriorMonth = priorMonth.atEndOfMonth() ;

相对于上个月末,获得前一个星期一,除非月末本身是星期一。使用TemporalAdjuster类中的TemporalAdjusters实现执行此操作。

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

关于java.time

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

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

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore