简体   繁体   中英

Flutter - How to find difference between two dates in years, months and days?

I'm looking for a way to use DateTime to parse two dates, to show the difference. I want to have it on the format: "X years, Y months, Z days".

For JS, we have momentjs library and following code ::

var a = moment([2015, 11, 29]);
var b = moment([2007, 06, 27]);

var years = a.diff(b, 'year');
b.add(years, 'years');

var months = a.diff(b, 'months');
b.add(months, 'months');

var days = a.diff(b, 'days');

console.log(years + ' years ' + months + ' months ' + days + ' days');
// 8 years 5 months 2 days

Is there similar library available for dart that can help achieve this usecase?

I think it is not possible to do exactly what you want easily with DateTime. Therefore you can use https://pub.dev/packages/time_machine package that is quite powerful with date time handling:

import 'package:time_machine/time_machine.dart';

void main() {
  LocalDate a = LocalDate.today();
  LocalDate b = LocalDate.dateTime(DateTime(2022, 1, 2));
  Period diff = b.periodSince(a);
  print("years: ${diff.years}; months: ${diff.months}; days: ${diff.days}");
}

for hours/minutes/seconds precision:

import 'package:time_machine/time_machine.dart';

void main() {
  LocalDateTime a = LocalDateTime.now();
  LocalDateTime b = LocalDateTime.dateTime(DateTime(2022, 1, 2, 10, 15, 47));
  Period diff = b.periodSince(a);
  print("years: ${diff.years}; months: ${diff.months}; days: ${diff.days}; hours: ${diff.hours}; minutes: ${diff.minutes}; seconds: ${diff.seconds}");
}

What you are looking for is the DartDateTime class You can get close to what you want in moment.js with

main() {
  var a = DateTime.utc(2015, 11, 29);
  var b = DateTime.utc(2007, 06, 27);

  var years = a.difference(b);
  print(years.inDays ~/365);

}

There is no inYears or inMonths option for DateTime though that's why the year is divided in the print. the difference function returns the difference in seconds so you have to process it yourself to days.

You could write an extension on duration class to format it:

extension DurationExtensions on Duration {
  String toYearsMonthsDaysString() {
    final years = this.inDays ~/ 365
    // You will need a custom logic for the months part, since not every month has 30 days
    final months = (this.inDays ~% 365) ~/ 30
    final days = (this.inDays ~% 365) ~% 30

    return "$years years $months months $days days";
  }
}

The usage will be:

final date1 = DateTime()
final date2 = DateTime()
date1.difference(date2).toYearsMonthsDaysString()

You can use Jiffy Package for this like this

var jiffy1 = Jiffy("2008-10", "yyyy-MM");
var jiffy2 = Jiffy("2007-1", "yyyy-MM");

jiff1.diff(jiffy2, Units.YEAR); // 1
jiff1.diff(jiffy2, Units.YEAR, true);

try intl package with the following code:

import 'package:intl/intl.dart';

String startDate = '01/01/2021';
String endDate = '01/01/2022';

final start = DateFormat('dd/MM/yyyy').parse(startDate);
final end = DateFormat('dd/MM/yyyy').parse(endDate);

Then, you can calculate the duration between the two dates with the following code:

final duration = end.difference(start);

To obtain the number of years, months and days, you can do the following:

final years = duration.inDays / 365;
final months = duration.inDays % 365 / 30;
final days = duration.inDays % 365 % 30;

Finally, you can use these variables to display the result in the desired format:

    final result = '${years.toInt()} years ${months.toInt()} months y ${days.toInt()} days';
final firstDate = DateTime.now();
final secondDate = DateTime(firstDate.year, firstDate.month - 20);

final yearsDifference = firstDate.year - secondDate.year;
final monthsDifference = (firstDate.year - secondDate.year) * 12 +
    firstDate.month - secondDate.month;
final totalDays = firstDate.difference(secondDate).inDays;

Simple approach, no packages needed.

I create my own class for Gregorian Dates, and i create a method which handle this issue, it calculates "logically" the difference between to dates in years, months, and days... i actually create the class from scratch without using any other packages (including DateTime package) but here i use DateTime package to illustrate how this method works.. until know it works fine for me...

method to determine if it's a leap year or no:

    static bool leapYear(DateTime date) {
    if(date.year%4 == 0) {
      if(date.year%100 == 0){
        return date.year%400 == 0;
      }
      return true;
    }
    return false;
  }

this is the method which calculate the difference between two dates in years, months, and days. it puts the result in a list of integers:

     static List<int> differenceInYearsMonthsDays(DateTime dt1, DateTime dt2) {
    List<int> simpleYear = [31,28,31,30,31,30,31,31,30,31,30,31];
    if(dt1.isAfter(dt2)) {
      DateTime temp = dt1;
      dt1 = dt2;
      dt2 = temp;
    }
    int totalMonthsDifference = ((dt2.year*12) + (dt2.month - 1)) - ((dt1.year*12) + (dt1.month - 1));
    int years = (totalMonthsDifference/12).floor();
    int months = totalMonthsDifference%12;
    late int days;
    if(dt2.day >= dt1.day) {days = dt2.day - dt1.day;}
    else {
      int monthDays = dt2.month == 3
          ? (leapYear(dt2)? 29: 28)
          : (dt2.month - 2 == -1? simpleYear[11]: simpleYear[dt2.month - 2]);
      int day = dt1.day;
      if(day > monthDays) day = monthDays;
      days = monthDays - (day - dt2.day);
      months--;
    }
    if(months < 0) {
      months = 11;
      years--;
    }
    return [years, months, days];
  }

the method which calculate the difference between two dates in months, and days:

static List<int> differenceInMonths(DateTime dt1, DateTime dt2){
    List<int> inYears = differenceInYearsMonthsDays(dt1, dt2);
    int difMonths = (inYears[0]*12) + inYears[1];
    return [difMonths, inYears[2]];
  }

the method which calculate the difference between two dates in days:

static int differenceInDays(DateTime dt1, DateTime dt2) {
    if(dt1.isAfter(dt2)) {
      DateTime temp = dt1;
      dt1 = dt2;
      dt2 = temp;
    }
    return dt2.difference(dt1).inDays;
  }

usage example:

void main() {
  DateTime date1 = DateTime(2005, 10, 3);
  DateTime date2 = DateTime(2022, 1, 12);
  List<int> diffYMD = GregorianDate.differenceInYearsMonthsDays(date1, date2);
  List<int> diffMD = GregorianDate.differenceInMonths(date1, date2);
  int diffD = GregorianDate.differenceInDays(date1, date2);

  print("The difference in years, months and days: ${diffYMD[0]} years, ${diffYMD[1]} months, and ${diffYMD[2]} days.");
  print("The difference in months and days: ${diffMD[0]} months, and ${diffMD[1]} days.");
  print("The difference in days: $diffD days.");
}

output:

The difference in years, months and days: 16 years, 3 months, and 9 days.
The difference in months and days: 195 months, and 9 days.
The difference in days: 5945 days.

DateTime difference in years is a specific function, like this:

  static int getDateDiffInYear(DateTime dateFrom, DateTime dateTo) {
    int sign = 1;
    if (dateFrom.isAfter(dateTo)) {
      DateTime temp = dateFrom;
      dateFrom = dateTo;
      dateTo = temp;
      sign = -1;
    }
    int years = dateTo.year - dateFrom.year;
    int months = dateTo.month - dateFrom.month;
    if (months < 0) {
      years--;
    } else {
      int days = dateTo.day - dateFrom.day;
      if (days < 0) {
        years--;
      }
    }
    return years * sign;
  }
DateTime a = DateTime(2015, 11, 29);
DateTime b = DateTime(2007, 06, 27);
int days = a.difference(b).inDays;

the answer is yes, you can easilly achieve it with DateTime class in Dart. See:https://api.dart.dev/stable/2.8.3/dart-core/DateTime-class.html

Example

void main() {
  var moonLanding = DateTime(1969,07,20)
  var marsLanding = DateTime(2024,06,10);
  var diff = moonLanding.difference(marsLanding);

  print(diff.inDays.abs());
  print(diff.inMinutes.abs());
  print(diff.inHours.abs());
}

outputs: 20049 28870560 481176

difHour = someDateTime.difference(DateTime.now()).inHours;
    difMin = (someDateTime.difference(DateTime.now()).inMinutes)-(difHour*60);

and same for years and days

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM