Add/Subtract months/years to date in dart?
Asked Answered
B

12

135

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

Berth answered 20/2, 2019 at 17:22 Comment(1)
I had a usefull comment below, but I will add it here: var newDate = new DateTime(date.year, date.month - 1, date.day); - if the current day is the last day off the month then wherever you go using months, you should land in the last day of the month (in cases like: when you go from 31.08 to 30.05, from 30.05 you go to 30.03 and not to 31.03) -Berth
B
173

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
Birdhouse answered 20/2, 2019 at 17:56 Comment(6)
It works but the problem is in momentjs/c# if you substract 6 months from 2000-08-31 you get 2000-02-29 and with dart you get 2000-03-02, which not so nice at all.Berth
Date arithmetic is hard, and definitions vary between implementations. Even time is odd... what happens when you add "1 day" that crosses the DST boundary? Good luck on getting something that works the way you want. :)Wilsey
Yes you are right, what I did in summary(the story is longer :) with more conditions) is if the current day is the last day off the month then wherever you go using months you land in the last day of the month (in cases of situations when you go from 31.08 to 30.05, from 30.05 you go to 30.03 and not to 31.03)Berth
Been using this extension: dartpad.dev/e3a6375e587ea8f8c61505b8a0888a38 based on your answer, it's pretty handfulVigesimal
@polRk so new DateTime(date.year, date.month - 50, date.day) does not work?Birdhouse
@Birdhouse it works fine in my country since we use negative month valueBunkhouse
F
128

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;
Francis answered 17/2, 2020 at 2:7 Comment(6)
I wanted to go from a monday to the previous monday and used this approach (date.subtract(Duration(days: 7));). However this approaches takes daylight saving times in consideration and the results you get may be off by one hour.Tribrach
This shouldn't be the answer because it doesn't solve the OP's problem that Duration doesn't take months or years as parameters. But it'll work fine for days, hours, minutes and/or seconds as you say :)Vanhorn
var myDate = DateTime.parse("2019-09-04 20:18:04Z"); myDate.add(Duration(days: 10)); print("myDate: $myDate"); it is printing myDate: 2019-09-04 20:18:04.000Z which is not correct solution.Dottie
The question was about adding months/years. And Duration doesn't have such properties at all!Fess
Duration does not have a years parameterDextrocular
You can use this: date.subtract(Duration(days: getDaysFromYear(numberOfYears))) to make it work for years. Here getDaysFromYear(int year) => (year * 365) + (year / 4).round(). It also accounts for leap years as well.Plaice
T
41

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
Twopiece answered 26/10, 2019 at 7:9 Comment(3)
interesting package. Would be even better if it was all based on extension methodsWestfall
Any time you recommend a piece of code you published or contributed to, it should be mentioned. (just for future reference)Straightjacket
I was facing some problem casting from Jiffy to DateTime. This ans helped me a lot. Thanks a lot for the contribution, DateTime d = Jiffy(DateTime(2018, 1, 13)).add(months: 6).dateTime; last dateTime saved my time.Electromotive
H
17

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

Heliograph answered 26/5, 2020 at 23:21 Comment(1)
DateTime createdAt = Timestamp.now().toDate(); createdAt.subtract(Duration(days: 7)); print("createdAt: $createdAt"); Not worked for me. Printing current timestamp, not seven 7 days earlier datetime . Kindly suggest. Thanks.Dottie
W
14

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);
Wager answered 29/1, 2021 at 14:26 Comment(1)
DateTime createdAt = Timestamp.now().toDate(); createdAt.subtract(Duration(days: 7)); print("createdAt: $createdAt"); Not worked for me. Printing current timestamp, not seven 7 days earlier datetime . Kindly suggest. Thanks.Dottie
M
11

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.

Marlyn answered 22/12, 2020 at 6:41 Comment(1)
You can use e.g. DateTime.utc(2017, 1, 1) to solve this if you are working with UTC. I had the same issue.Etom
C
9

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
Cane answered 17/3, 2022 at 3:45 Comment(0)
K
4

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.

Koffman answered 10/7, 2021 at 16:2 Comment(3)
DateTime createdAt = Timestamp.now().toDate(); createdAt.subtract(Duration(days: 7)); print("createdAt: $createdAt"); Not worked for me. Printing current timestamp, not seven 7 days earlier datetime . Kindly suggest. Thanks.Dottie
@Dottie "subtract" does not change the DateTime, it returns a new DateTime instead. So you have to change your code to createdAt = createdAt.subtract(Duration(days: 7));.Immigrant
This doesn't work when _selectedDate is March 30 and you subtract 1 month because February is 28 days.Mourant
S
3

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);
Sweated answered 9/1, 2023 at 12:36 Comment(0)
D
2

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);
Dahlberg answered 9/10, 2020 at 11:9 Comment(0)
C
1
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,
      );
}

Cockoftherock answered 20/6, 2021 at 12:22 Comment(2)
While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.Liverish
This doesn't work when now is March 30 and you subtract 1 month because February is 28 days.Mourant
N
0

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));
  });
}
Nougat answered 28/9, 2023 at 8:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.