preface

Date and Calendar, which are used by Java to deal with time and Date, have been criticized before. The main problem of Calendar is that its objects are mutable, while classes like time and Date should be immutable. In addition, its conceptual model is not clear, and the month calculation starts from 0, etc.

The JodaTime open source time/date library is a good alternative, and a new java.time library has been introduced in Java8 with a similar design concept to JodaTime.

Joda-time makes Time and date values easy to manage, manipulate, and understand. Ease of use is a major design goal of Joda. The joda-time main class DateTime can be converted to and from the older JDK classes Date and Calendar. This ensures compatibility with the JDK framework.

This paper mainly introduces the lower Period class and how to expand the correct difference between the two times by analyzing the construction method. See below for details

Common operations

Org.joda. time The logic of most computer programs and the elegant handling of dates and times using joda-time are well described. Let’s focus on the Period class that handles time periods (the difference between two dates)

Introduction of Period

An immutable time period specified by a set of duration field values

PeriodType is defined by the PeriodType class. The default PeriodType is standard, and the PeriodType can be year, month, week, day, hour, minute, second, or millisecond

The constructor

First: declare public directlyPeriod() { super(0L, (PeriodType)null, (Chronology)null); } Second: Public Period(int var1, int var2, int var3, int var4) {super(0, 0, 0, 0, var1, super(0, 0, 0, var1, super(0, 0, 0, var1, super(0, 0, var1, super)) var2, var3, var4, PeriodType.standard()); } Third: Public Period(ReadableInstant var1, ReadableInstant var2, DateTime) public Period(ReadableInstant var1, ReadableInstant var2, DateTime) PeriodType var3) { super(var1, var2, var3); }Copy the code

Correctly retrieves the difference between the two times

There are a lot of examples on the Internet about how to get information about the difference between two times, such as year, month and day:

Calculate the difference between the two times

DateTime start = new DateTime(2016,8,18,10,58);
DateTime end = new DateTime(2016,9,19,12,3);
Period period = new Period(start,end);        
System.out.println(period.getMonths()+"Month"+period.getDays()+"Day"
       +period.getHours()+"Hour"+period.getMinutes()+"Points");
Copy the code

The output is:

1 month 1 day 1 hour 5 minutes copy codeCopy the code

A Period automatically calculates the number of months, days, hours, etc.

There’s a problem that’s not addressed here take a case

DateTime d1 = new DateTime(2018,1,27,0,30);
DateTime d2 = new DateTime(2018,2,26,2,30);
Period p0 = new Period(d1, d2);
System.out.println(p0.getYears() + "Year" + p0.getMonths() + "Month"  + p0.getWeeks() + "Week" + p0.getDays() + "Day");
Copy the code

The output is:

0 years, 0 months, 4 weeks, 2 daysCopy the code

Is it inconsistent with the expected 30 days? Here’s why

Use new Period(ReadableInstant var1, PeriodType Public Period This constructor default uses PeriodType public Period(ReadableInstant var1, ReadableInstant var2) { super(var1, var2, (PeriodType)null); } The specified PeriodType is NULL. Protected BasePeriod(ReadableInstant var1, ReadableInstant var2, PeriodType var3) { //1. Check the corresponding value var3 = this.checkperiodType (var3);if(var1 == null && var2 == null) { //6. Here iType is assigned to the Period this.iType = var3; this.iValues = new int[this.size()]; }else{ long var4 = DateTimeUtils.getInstantMillis(var1); long var6 = DateTimeUtils.getInstantMillis(var2); Chronology var8 = DateTimeUtils.getIntervalChronology(var1, var2); this.iType = var3; this.iValues = var8.get(this, var4, var6); } } protected PeriodType checkPeriodType(PeriodType var1) { //2. Call getPeriodType() of the DateTimeUtils utility class, passing in VAR1 which is VAR3 of the previous block (i.e., NULL).returnDateTimeUtils.getPeriodType(var1); } public static final PeriodType getPeriodType(PeriodType var0) { //3. Here you can see that the null passed in is eventually converted to periodtype.standard ().returnvar0 == null ? PeriodType.standard() : var0; } //4. View the static method instance Standard on PeriodType and return the corresponding Period public static PeriodTypestandard() {
   PeriodType var0 = cStandard;
   ifPeriodType (var0 == null) {// You can see that PeriodType is specified in the Standard (look at the design of an instance of PeriodType) // The mystery is that periodis specified in the Standard!! var0 = new PeriodType("Standard", new DurationFieldType[]{DurationFieldType.years(), DurationFieldType.months(), DurationFieldType.weeks(), DurationFieldType.days(), DurationFieldType.hours(), DurationFieldType.minutes(), DurationFieldType.seconds(), DurationFieldType.millis()}, new int[]{0, 1, 2, 3, 4, 5, 6, 7});
   	cStandard = var0;
   }

   return var0;
}
Copy the code

So the correct posture for getting the difference between the two dates such as year, month and day should be as follows

DateTime d1 = new DateTime(2018,1,27,0,30); DateTime d2 = new DateTime(2018,2,26,2,30); / / specified PeriodType for yearMonthDayTime Period p2 = new Period (d1, d2, PeriodType yearMonthDayTime ()); System.out.println(p2.getYears() +"Year" + p2.getMonths() + "Month"+ p2.getWeeks() + "Week" + p2.getDays() + "Day");
Copy the code

Input result:

0 years, 0 months, 0 weeks, 30 daysCopy the code

Querying official Documents

public Period(ReadableInstant startInstant,
              ReadableInstant endInstant)
Copy the code

Most calculations performed by this method have obvious results. The special case is where the calculation is from a “long” month to a “short” month. Here, the result favours increasing the months field rather than the days. For example, 2013-01-31 to 2013-02-28 is treated as one whole month. By contrast, 2013-01-31 to 2013-03-30 is treated as one month and 30 days (exposed as 4 weeks and 2 days). The results are explained by considering that the start date plus the calculated period result in the end date.

There are two points:

  1. 2013-01-31 to 2013-03-30 is treated as one month and 30 days (exposed as 4 weeks and 2 days)

From 2013-01-31 to 2013-03-30 were considered to have one month and 30 days (with 30 days of exposure being 4 weeks and 2 days)

The reasons and implementation have been analyzed above, and if the desired value is obtained

  1. For example, 2013-01-31 to 2013-02-28 is a month

    2013-01-29 to 2013-02-28 is also a month

    2013-01-28 2013-02-28 is still a month

    2013-01-27 to 2013-02-28 is one month and one day

    This is also something to watch out for

conclusion

The author also used Period to deal with the difference between two times when joda.time was used in the project. However, some problems occurred in the process of using Period, which was different from the expected value. For more information, see the official documentation: User Guide.

The resources

Joda time official API

The thinking logic of a computer program