cosinus
cosinus

Reputation: 2155

Add/Subtract months/years to date in dart?

I saw that in dart there is a class Duration but it cant be used add/subtract years or month. How did you managed this issue, I need to subtract 6 months from an date. Is there something like moment.js for dart or something around? Thank you

Upvotes: 142

Views: 166564

Answers (14)

Dmitry Sikorsky
Dmitry Sikorsky

Reputation: 1501

This code will correctly move you from January 31, 2025 to February 28, 2025 by adding 1. Also, you can provide it with negative count.

extension DateTimeExtension on DateTime {
  DateTime addMonths(int count) {
    int baseMonth = year * 12 + (month - 1);
    int newMonth = baseMonth + count;
    int newYear = newMonth ~/ 12;

    newMonth = newMonth % 12 + 1;

    int oldDay = day;
    int daysInNewMonth = DateTime(newYear, newMonth + 1, 0).day;
    int newDay = oldDay <= daysInNewMonth ? oldDay : daysInNewMonth;

    return DateTime(newYear, newMonth, newDay);
  }
}

Upvotes: 0

Daud
Daud

Reputation: 19

You can use DateTime's existing copyWith method and insert the added/subtracted month or year in its parameter. This way, you can keep all the other DateTime's attributes (e.g., hours) without copying them manually. The copyWith method should also automatically handle overflow and underflow.

Example:

final date = DateTime(2024, 1, 1, 13);
print(date); // 2024-01-01 13:00:00.000
print(date.copyWith(month: date.month - 1)); // 2023-12-01 13:00:00.000
print(date.copyWith(year: date.year - 1)); // 2023-01-01 13:00:00.000

Upvotes: 0

Yuki.M
Yuki.M

Reputation: 435

As to Month, this may help.


extension DateTimeExtension on DateTime {
  DateTime addMonth(int month) {
    final expectedMonth = (this.month + month) % 12;
    DateTime result = DateTime(year, this.month + month, day, hour, minute, second, millisecond, microsecond);
    final isOverflow = expectedMonth < result.month;
    if (isOverflow) {
      return DateTime(result.year, result.month, 1, result.hour, result.minute, result.second, result.millisecond, result.microsecond)
        .add(const Duration(days: -1));
    } else {
      return result;
    }
  }
}

Test Code:

import 'package:flutter_test/flutter_test.dart';
import 'package:my_app/shared/date_time_extension.dart';

void main() {
  test('addMonth()', () {
    final dateTime = DateTime(2023, 3, 31, 0, 0, 0, 0, 0);
    expect(dateTime.addMonth(2), DateTime(2023, 5, 31, 0, 0, 0, 0, 0));
    expect(dateTime.addMonth(11), DateTime(2024, 2, 29, 0, 0, 0, 0, 0));
    expect(dateTime.addMonth(-1), DateTime(2023, 2, 28, 0, 0, 0, 0, 0));
    expect(dateTime.addMonth(-2), DateTime(2023, 1, 31, 0, 0, 0, 0, 0));
  });
}

Upvotes: 0

Ankit Mahadik
Ankit Mahadik

Reputation: 2435

In simple way without using any lib you can add Month and Year

var date = new DateTime(2021, 1, 29);

Adding Month :-

 date = DateTime(date.year, date.month + 1, date.day);

Adding Year :-

 date = DateTime(date.year + 1, date.month, date.day);

Upvotes: 14

Smily
Smily

Reputation: 3070

Okay so you can do that in two steps, taken from @zoechi (a big contributor to Flutter):

Define the base time, let us say:

var date = DateTime(2018, 1, 13);

Now, you want the new date:

var newDate = DateTime(date.year, date.month - 1, date.day);

And you will get

2017-12-13

Upvotes: 179

Jama Mohamed
Jama Mohamed

Reputation: 3405

Try out this package, Jiffy. Adds and subtracts date time. It follows the simple syntax of momentjs

You can add and subtract using the following units

years, months, weeks, days, hours, minutes, seconds, milliseconds and microseconds

To add 6 months

DateTime d = Jiffy.now().add(months: 6).dateTime; // 2020-04-26 10:05:57.469367
// You can also add you own Datetime object
DateTime d = Jiffy.parseFromDateTime(DateTime(2018, 1, 13)).add(months: 6).dateTime; // 2018-07-13 00:00:00.000

Another example

var jiffy = Jiffy.now().add(months: 5, years: 1);

DateTime d = jiffy.dateTime; // 2021-03-26 10:07:10.316874
// you can also format with ease
String s = jiffy.format("yyyy, MMM"); // 2021, Mar
// or default formats
String s = jiffy.yMMMMEEEEdjm; // Friday, March 26, 2021 10:08 AM

Upvotes: 43

aabiro
aabiro

Reputation: 4238

You can use the subtract and add methods

 date1.subtract(Duration(days: 7, hours: 3, minutes: 43, seconds: 56)); 

 date1.add(Duration(days: 1, hours: 23)));

Flutter Docs:

Subtract

Add

UPDATE

Above is the way to manually manipulate the date, to use years/months as parameters you can use Jiffy plugin, after install:

import 'package:jiffy/jiffy.dart';

DateTime d = Jiffy().subtract(months: 6).dateTime;  // 6 months from DateTime.now()
DateTime d = Jiffy().add(months: 6).dateTime; 

DateTime d = Jiffy(DateTime date).add(years: 6).dateTime;  // Ahead of a specific date given to Jifffy()
DateTime d = Jiffy(DateTime date).subtract(months: 6, years 3).dateTime;

Upvotes: 136

34m0
34m0

Reputation: 5945

I'm a fan of using extensions in dart, and we can use them here like this:

extension DateHelpers on DateTime {
  DateTime copyWith({
    int? year,
    int? month,
    int? day,
    int? hour,
    int? second,
    int? millisecond,
    int? microsecond,
  }) {
    return DateTime(
      year ?? this.year,
      month ?? this.month,
      day ?? this.day,
      hour ?? this.hour,
      second ?? this.second,
      millisecond ?? this.millisecond,
      microsecond ?? this.microsecond,
    );
  }

  DateTime addYears(int years) {
    return copyWith(year: this.year + years);
  }

  DateTime addMonths(int months) {
    return copyWith(month: this.month + months);
  }

  DateTime addWeeks(int weeks) {
    return copyWith(day: this.day + weeks*7);
  }

  DateTime addDays(int days) {
    return copyWith(day: this.day + days);
  }
}

You can then use this utility code as follows:

final now = DateTime.now();
final tomorrow = now.addDays(1);
final nextWeek = now.addWeeks(1);
final nextMonth = now.addMonths(1);
final nextYear = now.addYears(1);

Upvotes: 3

TechSatya
TechSatya

Reputation: 339

It's pretty straightforward.

Simply add or subtract with numbers on DateTime parameters based on your requirements.

For example -

~ Here I had a requirement of getting the date-time exactly 16 years before today even with milliseconds and in the below way I got my solution.

DateTime today = DateTime.now();
debugPrint("Today's date is: $today"); //Today's date is: 2022-03-17 09:08:33.891843

After desired subtraction;

  DateTime desiredDate = DateTime(
    today.year - 16,
    today.month,
    today.day,
    today.hour,
    today.minute,
    today.second,
    today.millisecond,
    today.microsecond,
  );
  debugPrint("16 years ago date is: $desiredDate"); // 16 years before date is: 2006-03-17 09:08:33.891843

Upvotes: 9

Jitesh Mohite
Jitesh Mohite

Reputation: 34170

Increase and Decrease of the day/month/year can be done by DateTime class

Initialise DateFormat which needed to be shown

  var _inputFormat = DateFormat('EE, d MMM yyyy');
  var _selectedDate = DateTime.now();

Increase Day/month/year:

_selectedDate = DateTime(_selectedDate.year,
                        _selectedDate.month + 1, _selectedDate.day);

Increase Day/month/year:

  _selectedDate = DateTime(_selectedDate.year,
                            _selectedDate.month - 1, _selectedDate.day);

Above example is for only month, similar way we can increase or decrease year and day.

Upvotes: 4

Ankur Kumar
Ankur Kumar

Reputation: 11

Future<void> main() async {
  final DateTime now = DateTime.now();
  var kdate = KDate.buildWith(now);
  log("YEAR", kdate.year);
  log("MONTH", kdate.month);
  log("DATE", kdate.date);
  log("Last Year", kdate.lastYear);
  log("Last Month", kdate.lastMonth);
  log("Yesturday", kdate.yesturday);
  log("Last Week Date", kdate.lastWeekDate);
}

void log(title, data) {
  print("\n$title  ====>  $data");
}

class KDate {
  KDate({
    this.now,
    required this.year,
    required this.month,
    required this.date,
    required this.lastYear,
    required this.lastMonth,
    required this.yesturday,
    required this.lastWeekDate,
  });
  final DateTime? now;
  final String? year;
  final String? month;
  final String? date;
  final String? lastMonth;
  final String? lastYear;
  final String? yesturday;
  final String? lastWeekDate;

  factory KDate.buildWith(DateTime now) => KDate(
        now: now,
        year: (now.year).toString().split(" ")[0],
        month: (now.month).toString().split(" ")[0],
        date: (now.day).toString().split(" ")[0],
        lastYear: (now.year - 1).toString().split(" ")[0],
        lastMonth: DateTime(now.year, now.month, now.month)
            .subtract(Duration(days: 28))
            .toString()
            .split(" ")[0]
            .toString()
            .split("-")[1],
        yesturday: DateTime(now.year, now.month, now.day)
            .subtract(Duration(days: 1))
            .toString()
            .split(" ")[0]
            .toString()
            .split("-")
            .last,
        lastWeekDate: DateTime(now.year, now.month, now.day)
            .subtract(Duration(days: 7))
            .toString()
            .split(" ")[0]
            .toString()
            .split("-")
            .last,
      );
}

Upvotes: 1

JCK&#246;del
JCK&#246;del

Reputation: 760

Not so simple.

final date = DateTime(2017, 1, 1);
final today = date.add(const Duration(days: 1451));

This results in 2020-12-21 23:00:00.000 because Dart considers daylight to calculate dates (so my 1451 days is missing 1 hour, and this is VERY dangerous (for example: Brazil abolished daylight savings in 2019, but if the app was written before that, the result will be forever wrong, same goes if the daylight savings is reintroduced in the future)).

To ignore the dayligh calculations, do this:

final date = DateTime(2017, 1, 1);
final today = DateTime(date.year, date.month, date.day + 1451);

Yep. Day is 1451 and this is OK. The today variable now shows the correct date and time: 2020-12-12 00:00:00.000.

Upvotes: 11

polRk
polRk

Reputation: 219

Can subtract any count of months.

  DateTime subtractMonths(int count) {
    var y = count ~/ 12;
    var m = count - y * 12;

    if (m > month) {
      y += 1;
      m = month - m;
    }

    return DateTime(year - y, month - m, day);
  }

Also works

DateTime(date.year, date.month + (-120), date.day);

Upvotes: 2

a.haggi
a.haggi

Reputation: 217

You can use subtract and add methods

Subtract

Add

But you have to reassign the result to the variable, which means:

This wouldn't work

 date1.add(Duration(days: 1, hours: 23)));

But this will:

 date1 = date1.add(Duration(days: 1, hours: 23)));

For example:

 void main() {
  var d = DateTime.utc(2020, 05, 27, 0, 0, 0);
  d.add(Duration(days: 1, hours: 23));
  // the prev line has no effect on the value of d
  print(d); // prints: 2020-05-27 00:00:00.000Z

  //But
  d = d.add(Duration(days: 1, hours: 23));
  print(d); // prints: 2020-05-28 23:00:00.000Z
}

Dartpad link

Upvotes: 16

Related Questions