Сделать алгоритм, который считает разницу между дати в днях
В общем сделал половину, но не могу сообразить как разобраться с датой, прошу помощи.
public class Main {
public static void main(String[] args) {
Date mass[] = new Date[3];
mass[0] = new Date(11, 9, 2020);
mass[1] = new Date( 2, 6, 2019);
mass[2] = new Date( 1, 5, 2020);
for (int i = 0; i < 3; i++)
mass[i].displayInfo();
mass[0].days();
mass[0].Date();
mass[2].Date();
}
}
class Date {
int year, month, day;
{
year=2021;
month=10;
day=7;
}
Date(int day) {
this.day = day;
}
Date(int day,int month) {
this.day = day;
this.month = month;
}
Date(int day, int month, int year) {
this.day = day;
this.month = month;
this.year = year;
}
void displayInfo(){
if(day < 10 && month < 10) {
System.out.printf("0%d.0%d.%d\n", day, month, year);
}
else if(month < 10){
System.out.printf("%d.0%d.%d\n", day, month, year);
}
else if(day < 10){
System.out.printf("0%d.%d.%d\n", day, month, year);
}
else
System.out.printf("%d.%d.%d\n", day, month, year);
}
public int days(){
int num = 0, cal = 0, Tot = 365;
for (int i = 1; i < month; i++) {
if (i == 2) {
if (year % 4 == 0)
num += 29;
else
num += 28;
} else if (i == 1 || i == 3 || i == 5 || i == 7
|| i == 8 || i == 10 || i == 12)
num += 31;
else
num += 30;
}
if (Tot != 365) {
System.out.println("Not valid");
} else {
cal = Tot - (day + num);
System.out.println("Remaining month of Days=" + (num + day));
}
return 0;
}
}
Ответы (1 шт):
Если известно количество дней, прошедших с начала года в текущем году (которые вычисляются в методе Date::days()), то алгоритм расчёта количества дней между двумя датами вполне прост:
- Если даты относятся к одному году, то количество дней между ними составит разницу между значениями
that.days() - this.days() - Иначе нужно определить меньшую дату
from, вычислить для неё количество дней до конца года365/366 - from.days(), прибавить количество дней для второй датыtoи добавить количество дней в каждом году между двумя данными датами, с учётом знака между датами.
Для определения меньшей даты имеет смысл реализовать метод compareTo(Date d) из интерфейса Comparable.
Также нужно корректно реализовать метод isLeapYear() -- как известно, високосный год каждые 4 года считался по юлианскому календарю, а в григорианском календаре года, кратные 100, не являются високосными, если только они не кратны 400.
Методы days() и displayInfo() также следует отрефакторить: первый не реализован корректно (всегда возвращает 0), во втором нужно правильно выбрать формат для вывода нулей перед днём/месяцем "%02d".
Итак, класс Date без избыточных конструкторов может выглядеть так:
class Date implements Comparable<Date> {
private static final int[] DAYS = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
private static final int TOTAL = 365;
private final int year, month, day; // сделать поля неизменяемыми
public Date(int d, int m, int y) {
this.year = y;
this.month = m;
this.day = d;
}
public int getYear() { return year; }
public int getMonth() { return month; }
public int getDay() { return day; }
public void print() {
System.out.println(this);
}
@Override
public String toString() {
return String.format("%02d.%02d.%4d", day, month, year);
}
public int days() {
int d = 0;
for (int m = 1; m < month; m++) {
d += DAYS[m - 1];
if (m == 2) {
d += isLeapYear();
}
}
d += day;
return d;
}
public int isLeapYear() {
return Date.isLeapYear(this.year);
}
public static int isLeapYear(int y) {
return y % 400 == 0 || y % 100 != 0 && y % 4 == 0 ? 1 : 0;
}
@Override
public int compareTo(Date that) {
int res = Integer.compare(this.year, that.year);
if (res == 0) {
res = Integer.compare(this.month, that.month);
}
if (res == 0) {
res = Integer.compare(this.day, that.day);
}
return res;
}
public int daysBetween(Date that) {
System.out.println("Days between: " + this + " and " + that);
// следующие строки можно раскомментировать чтобы сравнить данные вычисления
// с корректными методами в Java Date/Time API
// LocalDate df = LocalDate.of(this.year, this.month, this.day);
// LocalDate dt = LocalDate.of(that.year, that.month, that.day);
// System.out.println("Days between: " + df + " and " + dt + " = " + ChronoUnit.DAYS.between(df, dt));
if (this.year == that.year) {
return that.days() - this.days();
}
// найти меньшую дату
Date from = this.compareTo(that) <= 0 ? this : that;
Date to = this.compareTo(that) > 0 ? this : that;
int sign = this.compareTo(that) <= 0 ? 1 : -1;
int d = TOTAL + Date.isLeapYear(from.year) - from.days() + to.days();
for (int y = from.year + 1; y < to.year; y++) {
d += TOTAL + Date.isLeapYear(y);
}
return sign * d;
}
}
Тесты:
Date arr[] = {
new Date(11, 9, 2020),
new Date( 2, 6, 2019),
new Date( 1, 5, 2020),
};
for (Date d : arr) {
d.print();
System.out.println(d.days());
}
System.out.println(arr[0].daysBetween(arr[2]));
Результаты:
11.09.2020
255
02.06.2019
153
01.05.2020
122
Days between: 11.09.2020 and 01.05.2020
-133
