[
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Build\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n  schedule:\n    # runs the CI weekly\n    - cron: \"0 0 * * 0\"\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v6\n      - uses: dart-lang/setup-dart@v1\n        with:\n          sdk: dev\n\n      - name: Install dependencies\n        run: dart pub get\n\n      - name: Check format\n        run: dart format --output=none --set-exit-if-changed -l 120 lib\n\n      - name: Analyze\n        run: dart analyze lib\n\n      - name: Run tests\n        run: dart test --coverage coverage\n\n      - name: Coverage\n        run: dart run coverage:format_coverage -l -i ./coverage/test/time_test.dart.vm.json -o ./coverage/lcov.info\n\n      - name: Upload coverage to codecov\n        uses: codecov/codecov-action@v5\n        with:\n          token: ${{ secrets.CODECOV_TOKEN }}\n          fail_ci_if_error: true\n"
  },
  {
    "path": ".gitignore",
    "content": "# Files and directories created by pub\n.dart_tool/\n.packages\ntest/.test_coverage.dart\ncoverage/\ncoverage_badge.svg\npubspec.lock\n\n# Conventional directory for build outputs\nbuild/\n\n# Directory created by dartdoc\ndoc/api/\n\n# JetBrains IDEs\n.idea/*\n*.iml\n*.ipr\n*.iws\n"
  },
  {
    "path": ".pubignore",
    "content": ".idea/*\ncoverage/*\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  \"dart.lineLength\": 120,\n  \"[dart]\": {\n      \"editor.tabSize\": 2,\n      \"editor.rulers\": [\n          120\n      ],\n  },\n}"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## 2.1.6\n\n- Include `milliseconds` and `microseconds` in `timeOfDay` extension to `DateTime`\n\n## 2.1.5\n\n- Introduce `endOfDay` extension to `DateTime`\n\n## 2.1.4\n\n- Introduce `shift` extension to `DateTime`\n\n## 2.1.3\n\n- Introduce `isWeekend` extension to `DateTime`\n- Introduce `isWorkday` extension to `DateTime`\n\n## 2.1.2\n\n- Fix `min` and `max` assertion with `clamp` extension\n\n## 2.1.1\n\n- Introduce `firstDayOfWeek` extension to `DateTime`\n- Introduce `lastDayOfWeek` extension to `DateTime`\n- Introduce `firstDayOfMonth` extension to `DateTime`\n- Introduce `lastDayOfMonth` extension to `DateTime`\n- Introduce `firstDayOfYear` extension to `DateTime`\n- Introduce `lastDayOfYear` extension to `DateTime`\n- Introduce `clamp` extension to `DateTime`\n- Introduce `clamp` extension to `Duration`\n\n## 2.1.0\n\n- Introduce `package:clock` dependency for more predictable testing\n\n## 2.0.1\n\n- Implement utc support for `copyWith` operation\n\n## 2.0.0\n\n- Migrate to null-safety\n\n## 1.5.0-nullsafety.1\n\n- Introduce `isAtSameYearAs` extension to `DateTime`\n- Introduce `isAtSameMonthAs` extension to `DateTime`\n- Introduce `isAtSameDayAs` extension to `DateTime`\n- Introduce `isAtSameHourAs` extension to `DateTime`\n- Introduce `isAtSameMinuteAs` extension to `DateTime`\n- Introduce `isAtSameMillisecondAs` extension to `DateTime`\n- Introduce `isAtSameMicrosecondAs` extension to `DateTime`\n- Introduce `isLeapYear` extension to `DateTime`\n- Introduce `daysInMonth` extension to `DateTime`\n\n```dart\nfinal DateTime specificDate = DateTime(2021, 01, 01);\nfinal DateTime otherDate = DateTime(2021, 02, 01);\n\nprint(specificDate.isAtSameYearAs(otherDate)); // true\nprint(specificDate.isAtSameMonthAs(otherDate)); // false\nprint(specificDate.isAtSameDayAs(otherDate)); // false\n```\n\n## 1.4.1\n\n- Introduce `isAtSameYearAs` extension to `DateTime`\n- Introduce `isAtSameMonthAs` extension to `DateTime`\n- Introduce `isAtSameDayAs` extension to `DateTime`\n- Introduce `isAtSameHourAs` extension to `DateTime`\n- Introduce `isAtSameMinuteAs` extension to `DateTime`\n- Introduce `isAtSameMillisecondAs` extension to `DateTime`\n- Introduce `isAtSameMicrosecondAs` extension to `DateTime`\n- Introduce `isLeapYear` extension to `DateTime`\n- Introduce `daysInMonth` extension to `DateTime`\n\n## 1.5.0-nullsafety.0\n- Migrated to null-safe dart\n\n## 1.4.0\n\n- Introduce `isToday` extension to `Duration`\n- Introduce `isTomorrow` extension to `DateTime`\n- Introduce `wasYesterday` extension to `DateTime`\n\n## 1.3.0\n\n- Introduce `delay` extension to `Duration`\n- Introduce `copyWith` extension to `DateTime`\n\n## 1.2.0\n\n- Iterate through a `DateTime` range:\n\n```dart\nfinal DateTime start = DateTime(2019, 12, 2);\nfinal DateTime end = start + 1.weeks;\nfinal DateTime tuesday = start.to(end).firstWhere((date) => date.weekday == DateTime.tuesday);\n```\n\n## 1.1.1\n\n- Fix breaking change from v1.1.0 by introducing @deprecated flag\n\n## 1.1.0\n\n- Breaking Change: renamed `later` to `fromNow` to align with other ecosystems\n- Introduced support for other variants of `num` i.e `double`\n\n## 1.0.0\n\n- Named extensions to allow discoverability\n- Introduced quality control test cases\n\n## 0.0.1+1\n\n- Unify extensions for int, Duration & DateTime\n\n## 0.0.1\n\n- Initial version\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 Jeremiah Ogbomo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# ⏰ Time\n\n\n[![Build](https://github.com/jogboms/time.dart/actions/workflows/build.yml/badge.svg)](https://github.com/jogboms/time.dart/actions/workflows/build.yml) [![codecov](https://codecov.io/gh/jogboms/time.dart/branch/master/graph/badge.svg)](https://codecov.io/gh/jogboms/time.dart) [![pub package](https://img.shields.io/pub/v/time.svg)](https://pub.dartlang.org/packages/time)\n\nWith shiny extensions, if you have ever written something like this, then look no further:\n\n```dart\nfinal DateTime fourHoursFromNow = DateTime.now() + Duration(hours: 4);\n```\n\n## 🎖 Installation\n```yaml\ndependencies:\n  time: \"^2.1.6\"\n```\n\n### ⚡ Import\n\n```dart\nimport 'package:time/time.dart';\n```\n\n## 🎮 Usage\n\n```dart\nfinal Duration tenMinutes = 10.minutes;\nfinal Duration oneHourThirtyMinutes = 1.5.hours;\nfinal DateTime afterTenMinutes = DateTime.now() + 10.minutes;\nfinal Duration tenMinutesAndSome = 10.minutes + 15.seconds;\nfinal int tenMinutesInSeconds = 10.minutes.inSeconds;\nfinal DateTime tenMinutesFromNow = 10.minutes.fromNow;\n```\n\nYou can perform all basic arithmetic operations on `Duration` as you always have been:\n\n```dart\nfinal Duration interval = 10.minutes + 15.seconds - 3.minutes + 2.hours;\nfinal Duration doubled = interval * 2;\n```\n\nYou can also use these operations on `DateTime`:\n\n```dart\nfinal DateTime oneHourAfter = DateTime() + 1.hours;\n```\n\n`Duration` is easily convertible as it always has been:\n\n```dart\nfinal int twoMinutesInSeconds = 2.minutes.inSeconds;\n```\n\nYou can also convert `Duration` to `DateTime`, if needed:\n\n```dart\nfinal DateTime timeInFuture = 5.minutes.fromNow;\nfinal DateTime timeInPast = 5.minutes.ago;\n```\n\nIterate through a `DateTime` range:\n\n```dart\nfinal DateTime start = DateTime(2019, 12, 2);\nfinal DateTime end = start + 1.weeks;\nfinal DateTime tuesday = start.to(end).firstWhere((date) => date.weekday == DateTime.tuesday);\n```\n\nGranular comparison between `DateTime` fields:\n\n```dart\nfinal DateTime specificDate = DateTime(2021, 01, 01);\nfinal DateTime otherDate = DateTime(2021, 02, 01);\n\nprint(specificDate.isAtSameYearAs(otherDate)); // true\nprint(specificDate.isAtSameMonthAs(otherDate)); // false\nprint(specificDate.isAtSameDayAs(otherDate)); // false\n```\n\nYou can also delay code execution:\n\n```dart\nvoid doSomething() async {\n  await 5.seconds.delay;\n  // Do the other things\n}\n```\n\nYou can also use the popular `copyWith`:\n\n```dart\nfinal initial = DateTime(2019, 2, 4, 24, 50, 45, 1, 1);\nfinal expected = initial.copyWith(\n  year: 2021,\n  month: 10,\n  day: 28,\n  hour: 12,\n  minute: 45,\n  second: 10,\n  millisecond: 0,\n  microsecond: 12,\n);\n```\n\nVisit the [API Reference](https://pub.dev/documentation/time/latest/time/time-library.html) to find out all that is available.\n\n## 🐛 Bugs/Requests\n\nIf you encounter any problems feel free to open an issue. If you feel the library is missing a feature, please raise a ticket on Github and I'll look into it. Pull request are also welcome.\n\n## 👏 Inspiration\n\n- Swift library of the same name - [Time](https://github.com/dreymonde/Time).\n- Kotlin library of the same name - [Time](https://github.com/kizitonwose/Time).\n\n## ⭐ License\n\nMIT License\n"
  },
  {
    "path": "analysis_options.yaml",
    "content": "include: package:lints/recommended.yaml\n\nanalyzer:\n  strong-mode:\n    implicit-casts: false\n    implicit-dynamic: false\n  errors:\n    missing_required_param: error\n    missing_return: error\n    unused_import: error\n    unused_local_variable: error\n    dead_code: error\n"
  },
  {
    "path": "example/time_example.dart",
    "content": "import 'package:time/time.dart';\n\nvoid main() async {\n  // Num Extensions\n  print(1.weeks);\n  print(1.5.weeks);\n  print(7.days);\n  print(7.5.days);\n  print(22.hours);\n  print(22.5.hours);\n  print(45.minutes);\n  print(45.5.minutes);\n  print(30.seconds);\n  print(30.5.seconds);\n  print(15.milliseconds);\n  print(15.5.milliseconds);\n  print(10.microseconds);\n  print(10.5.microseconds);\n  print(5.nanoseconds);\n  print(5.5.nanoseconds);\n\n  // Delay for 5 seconds\n  await 5.seconds.delay;\n\n  // DateTime Extensions\n  print(DateTime.now() + 7.days);\n  print(DateTime.now() - 7.days);\n  print(\n    DateTime(2019, 2, 4, 24, 50, 45, 1, 1).copyWith(\n      year: 2021,\n      month: 10,\n      day: 28,\n      hour: 12,\n      minute: 45,\n      second: 10,\n      millisecond: 0,\n      microsecond: 12,\n    ),\n  );\n\n  // Duration Extensions\n  print(7.days.inWeeks);\n  print(7.days.fromNow);\n  print(7.days.ago);\n\n  DateTime.now().to(1.weeks.fromNow, by: 1.days).forEach(print);\n}\n"
  },
  {
    "path": "lib/src/extensions.dart",
    "content": "import 'package:clock/clock.dart';\n\nextension NumTimeExtension<T extends num> on T {\n  /// Returns a Duration represented in weeks\n  Duration get weeks => days * DurationTimeExtension.daysPerWeek;\n\n  /// Returns a Duration represented in days\n  Duration get days => milliseconds * Duration.millisecondsPerDay;\n\n  /// Returns a Duration represented in hours\n  Duration get hours => milliseconds * Duration.millisecondsPerHour;\n\n  /// Returns a Duration represented in minutes\n  Duration get minutes => milliseconds * Duration.millisecondsPerMinute;\n\n  /// Returns a Duration represented in seconds\n  Duration get seconds => milliseconds * Duration.millisecondsPerSecond;\n\n  /// Returns a Duration represented in milliseconds\n  Duration get milliseconds => Duration(microseconds: (this * Duration.microsecondsPerMillisecond).toInt());\n\n  /// Returns a Duration represented in microseconds\n  Duration get microseconds => milliseconds ~/ Duration.microsecondsPerMillisecond;\n\n  /// Returns a Duration represented in nanoseconds\n  Duration get nanoseconds => microseconds ~/ DurationTimeExtension.nanosecondsPerMicrosecond;\n}\n\nextension DateTimeTimeExtension on DateTime {\n  /// Adds this DateTime and Duration and returns the sum as a new DateTime object.\n  DateTime operator +(Duration duration) => add(duration);\n\n  /// Subtracts the Duration from this DateTime returns the difference as a new DateTime object.\n  DateTime operator -(Duration duration) => subtract(duration);\n\n  /// Returns only year, month and day\n  DateTime get date => isUtc ? DateTime.utc(year, month, day) : DateTime(year, month, day);\n\n  /// Returns only the time\n  Duration get timeOfDay =>\n      hour.hours + minute.minutes + second.seconds + millisecond.milliseconds + microsecond.microseconds;\n\n  /// Returns if today, true\n  bool get isToday {\n    return _calculateDifference(this) == 0;\n  }\n\n  /// Returns if tomorrow, true\n  bool get isTomorrow {\n    return _calculateDifference(this) == 1;\n  }\n\n  /// Returns if yesterday, true\n  bool get wasYesterday {\n    return _calculateDifference(this) == -1;\n  }\n\n  /// Returns true if this year is a leap year.\n  bool get isLeapYear =>\n      // Leap years are used since 1582.\n      year >= 1582 && year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);\n\n  /// Returns the amount of days that are in this month.\n  ///\n  /// Accounts for leap years.\n  int get daysInMonth {\n    final days = [\n      31, // January\n      if (isLeapYear) 29 else 28, // February\n      31, // March\n      30, // April\n      31, // May\n      30, // June\n      31, // July\n      31, // August\n      30, // September\n      31, // October\n      30, // November\n      31, // December\n    ];\n\n    return days[month - 1];\n  }\n\n  /// Returns true if [other] is in the same year as [this].\n  ///\n  /// Does not account for timezones.\n  bool isAtSameYearAs(DateTime other) => year == other.year;\n\n  /// Returns true if [other] is in the same month as [this].\n  ///\n  /// This means the exact month, including year.\n  ///\n  /// Does not account for timezones.\n  bool isAtSameMonthAs(DateTime other) => isAtSameYearAs(other) && month == other.month;\n\n  /// Returns true if [other] is on the same day as [this].\n  ///\n  /// This means the exact day, including year and month.\n  ///\n  /// Does not account for timezones.\n  bool isAtSameDayAs(DateTime other) => isAtSameMonthAs(other) && day == other.day;\n\n  /// Returns true if [other] is at the same hour as [this].\n  ///\n  /// This means the exact hour, including year, month and day.\n  ///\n  /// Does not account for timezones.\n  bool isAtSameHourAs(DateTime other) => isAtSameDayAs(other) && hour == other.hour;\n\n  /// Returns true if [other] is at the same minute as [this].\n  ///\n  /// This means the exact minute, including year, month, day and hour.\n  ///\n  /// Does not account for timezones.\n  bool isAtSameMinuteAs(DateTime other) => isAtSameHourAs(other) && minute == other.minute;\n\n  /// Returns true if [other] is at the same second as [this].\n  ///\n  /// This means the exact second, including year, month, day, hour and minute.\n  ///\n  /// Does not account for timezones.\n  bool isAtSameSecondAs(DateTime other) => isAtSameMinuteAs(other) && second == other.second;\n\n  /// Returns true if [other] is at the same millisecond as [this].\n  ///\n  /// This means the exact millisecond,\n  /// including year, month, day, hour, minute and second.\n  ///\n  /// Does not account for timezones.\n  bool isAtSameMillisecondAs(DateTime other) => isAtSameSecondAs(other) && millisecond == other.millisecond;\n\n  /// Returns true if [other] is at the same microsecond as [this].\n  ///\n  /// This means the exact microsecond,\n  /// including year, month, day, hour, minute, second and millisecond.\n  ///\n  /// Does not account for timezones.\n  bool isAtSameMicrosecondAs(DateTime other) => isAtSameMillisecondAs(other) && microsecond == other.microsecond;\n\n  static int _calculateDifference(DateTime date) {\n    final now = clock.now();\n    return DateTime(date.year, date.month, date.day).difference(DateTime(now.year, now.month, now.day)).inDays;\n  }\n\n  /// Returns a range of dates to [to], exclusive start, inclusive end\n  /// ```dart\n  /// final start = DateTime(2019);\n  /// final end = DateTime(2020);\n  /// start.to(end, by: const Duration(days: 365)).forEach(print); // 2020-01-01 00:00:00.000\n  /// ```\n  Iterable<DateTime> to(DateTime to, {Duration by = const Duration(days: 1)}) sync* {\n    if (isAtSameMomentAs(to)) return;\n\n    if (isBefore(to)) {\n      var value = this + by;\n      yield value;\n\n      var count = 1;\n      while (value.isBefore(to)) {\n        value = this + (by * ++count);\n        yield value;\n      }\n    } else {\n      var value = this - by;\n      yield value;\n\n      var count = 1;\n      while (value.isAfter(to)) {\n        value = this - (by * ++count);\n        yield value;\n      }\n    }\n  }\n\n  DateTime copyWith({\n    int? year,\n    int? month,\n    int? day,\n    int? hour,\n    int? minute,\n    int? second,\n    int? millisecond,\n    int? microsecond,\n  }) {\n    return isUtc\n        ? DateTime.utc(\n            year ?? this.year,\n            month ?? this.month,\n            day ?? this.day,\n            hour ?? this.hour,\n            minute ?? this.minute,\n            second ?? this.second,\n            millisecond ?? this.millisecond,\n            microsecond ?? this.microsecond,\n          )\n        : DateTime(\n            year ?? this.year,\n            month ?? this.month,\n            day ?? this.day,\n            hour ?? this.hour,\n            minute ?? this.minute,\n            second ?? this.second,\n            millisecond ?? this.millisecond,\n            microsecond ?? this.microsecond,\n          );\n  }\n\n  /// Returns the Monday of this week\n  DateTime get firstDayOfWeek =>\n      isUtc ? DateTime.utc(year, month, day + 1 - weekday) : DateTime(year, month, day + 1 - weekday);\n\n  /// Returns the Sunday of this week\n  DateTime get lastDayOfWeek =>\n      isUtc ? DateTime.utc(year, month, day + 7 - weekday) : DateTime(year, month, day + 7 - weekday);\n\n  /// Returns the first day of this month\n  DateTime get firstDayOfMonth => isUtc ? DateTime.utc(year, month, 1) : DateTime(year, month, 1);\n\n  /// Returns the last day of this month (considers leap years)\n  DateTime get lastDayOfMonth => isUtc ? DateTime.utc(year, month + 1, 0) : DateTime(year, month + 1, 0);\n\n  /// Returns the first day of this year\n  DateTime get firstDayOfYear => isUtc ? DateTime.utc(year, 1, 1) : DateTime(year, 1, 1);\n\n  /// Returns the last day of this year\n  DateTime get lastDayOfYear => isUtc ? DateTime.utc(year, 12, 31) : DateTime(year, 12, 31);\n\n  /// Returns this [DateTime] clamped to be in the range [min]-[max].\n  ///\n  /// The comparison is done using [compareTo].\n  ///\n  /// The arguments [min] and [max] must form a valid range where\n  /// `min.compareTo(max) <= 0`.\n  ///\n  /// Example:\n  /// ```dart\n  /// var result = DateTime(2022, DateTime.october, 15).clamp(\n  ///   min: DateTime(2022, DateTime.september, 1),\n  ///   max: DateTime(2022, DateTime.september, 30),\n  /// ); // DateTime(2022, DateTime.september, 30);\n  /// result = DateTime(2022, DateTime.august, 21).clamp(\n  ///   min: DateTime(2022, DateTime.september, 15),\n  ///   max: DateTime(2022, DateTime.september, 30),\n  /// ); // DateTime(2022, DateTime.september, 15);\n  /// result = DateTime(2022, DateTime.september, 1).clamp(\n  ///   min: DateTime(2022, DateTime.august, 1),\n  ///   max: DateTime(2022, DateTime.september, 30),\n  /// ); // DateTime(2022, DateTime.september, 1);\n  /// ```\n  DateTime clamp({DateTime? min, DateTime? max}) {\n    assert(\n      ((min != null) && (max != null)) ? (min.isBefore(max) || (min == max)) : true,\n      'DateTime min has to be before or equal to max\\n(min: $min - max: $max)',\n    );\n    if ((min != null) && compareTo(min).isNegative) {\n      return min;\n    } else if ((max != null) && max.compareTo(this).isNegative) {\n      return max;\n    }\n    return this;\n  }\n\n  /// Adds time units to the calendar date and/or clock time.\n  ///\n  /// Creates a new [DateTime] object with a calendar date offset from\n  /// that of the the current one by the provided number of years, months, and/or days,\n  /// and a wall clock time offset from that of the current one by the provided\n  /// hours, minutes, seconds, milliseconds and/or microseconds.\n  ///\n  /// The provided time units can be positive or negative, or any combination.\n  /// Overflowing, say by adding more than 30 days to a any date, works like\n  /// in the [DateTime] constructor.\n  /// The resulting day and time must be within the supported range for\n  /// the `DateTime` class.\n  DateTime shift({\n    int years = 0,\n    int months = 0,\n    int days = 0,\n    int hours = 0,\n    int minutes = 0,\n    int seconds = 0,\n    int milliseconds = 0,\n    int microseconds = 0,\n  }) =>\n      copyWith(\n        year: year + years,\n        month: month + months,\n        day: day + days,\n        hour: hour + hours,\n        minute: minute + minutes,\n        second: second + seconds,\n        millisecond: millisecond + milliseconds,\n        microsecond: microsecond + microseconds,\n      );\n\n  bool get isWeekend => (weekday == DateTime.saturday) || (weekday == DateTime.sunday);\n\n  bool get isWorkday => !isWeekend;\n\n  /// Returns the last microsecond of the day (23:59:59.999999)\n  /// ```dart\n  /// final date = DateTime(2020, 1, 1);\n  /// date.endOfDay; // 2020-01-01 23:59:59.999999\n  /// final date = DateTime(2020, 1, 1, 12, 30, 15, 123, 456);\n  /// date.endOfDay; // 2020-01-01 23:59:59.999999\n  /// ```\n  DateTime get endOfDay {\n    const microsecond = Duration(microseconds: 1);\n    if (isUtc) return DateTime.utc(year, month, day + 1) - microsecond;\n    return DateTime(year, month, day + 1) - microsecond;\n  }\n}\n\nextension DurationTimeExtension on Duration {\n  static const int daysPerWeek = 7;\n  static const int nanosecondsPerMicrosecond = 1000;\n\n  /// Returns the representation in weeks\n  int get inWeeks => (inDays / daysPerWeek).ceil();\n\n  /// Adds the Duration to the current DateTime and returns a DateTime in the future\n  DateTime get fromNow => clock.now() + this;\n\n  /// Subtracts the Duration from the current DateTime and returns a DateTime in the past\n  DateTime get ago => clock.now() - this;\n\n  /// Returns a Future.delayed from this\n  Future<void> get delay => Future.delayed(this);\n\n  /// Returns this [Duration] clamped to be in the range [min]-[max].\n  ///\n  /// The comparison is done using [compareTo].\n  ///\n  /// The arguments [min] and [max] must form a valid range where\n  /// `min.compareTo(max) <= 0`.\n  ///\n  /// Example:\n  /// ```dart\n  /// var result = Duration(days: 10, hours: 12).clamp(\n  ///   min: Duration(days: 5),\n  ///   max: Duration(days: 10),\n  /// ); // Duration(days: 10)\n  /// result = Duration(hours: 18).clamp(\n  ///   min: Duration(days: 5),\n  ///   max: Duration(days: 10),\n  /// ); // Duration(days: 5)\n  /// result = Duration(days: 0).clamp(\n  ///   min: Duration(days: -5),\n  ///   max: Duration(days: 5),\n  /// ); // Duration(days: 0)\n  /// ```\n  Duration clamp({Duration? min, Duration? max}) {\n    assert(\n      ((min != null) && (max != null)) ? min.compareTo(max) <= 0 : true,\n      'Duration min has to be shorter than max\\n(min: $min - max: $max)',\n    );\n    if ((min != null) && compareTo(min).isNegative) {\n      return min;\n    } else if ((max != null) && max.compareTo(this).isNegative) {\n      return max;\n    }\n    return this;\n  }\n}\n"
  },
  {
    "path": "lib/time.dart",
    "content": "library time;\n\nexport './src/extensions.dart';\n"
  },
  {
    "path": "pubspec.yaml",
    "content": "name: time\ndescription: Type-safe DateTime and Duration calculations, powered by extensions.\nversion: 2.1.6\nhomepage: https://github.com/jogboms/time.dart\n\nenvironment:\n  sdk: \">=2.12.0 <4.0.0\"\n\ndependencies:\n  clock: \">=1.1.1 <2.0.0\"\n\nfunding:\n  - https://www.paypal.me/jogboms\n  - https://www.buymeacoffee.com/jogboms\n\ndev_dependencies:\n  lints: ^6.0.0\n  test: ^1.28.0\n  coverage: ^1.15.0\n"
  },
  {
    "path": "test/time_test.dart",
    "content": "import 'package:clock/clock.dart';\nimport 'package:test/test.dart';\nimport 'package:time/time.dart';\n\nvoid main() {\n  final date = DateTime(2000, 1, 1);\n\n  group('TimeExtension', () {\n    group('Integers', () {\n      test('can be converted into weeks', () {\n        expect(1.weeks, Duration(days: 7));\n      });\n\n      test('can be converted into days', () {\n        expect(5.days, Duration(days: 5));\n      });\n\n      test('can be converted into hours', () {\n        expect(22.hours, Duration(hours: 22));\n      });\n\n      test('can be converted into minutes', () {\n        expect(45.minutes, Duration(minutes: 45));\n      });\n\n      test('can be converted into seconds', () {\n        expect(30.seconds, Duration(seconds: 30));\n      });\n\n      test('can be converted into milliseconds', () {\n        expect(15.milliseconds, Duration(milliseconds: 15));\n      });\n\n      test('can be converted into microseconds', () {\n        expect(10.microseconds, Duration(microseconds: 10));\n      });\n\n      test('can be converted into nanoseconds', () {\n        expect(5.nanoseconds, Duration(microseconds: 5 ~/ 1000));\n      });\n    });\n\n    group('Double', () {\n      test('can be converted into weeks', () {\n        expect(1.5.weeks, Duration(days: 10, hours: 12));\n      });\n\n      test('can be converted into days', () {\n        expect(5.5.days, Duration(days: 5, hours: 12));\n      });\n\n      test('can be converted into hours', () {\n        expect(22.5.hours, Duration(hours: 22, minutes: 30));\n      });\n\n      test('can be converted into minutes', () {\n        expect(45.5.minutes, Duration(minutes: 45, seconds: 30));\n      });\n\n      test('can be converted into seconds', () {\n        expect(30.5.seconds, Duration(seconds: 30, milliseconds: 500));\n      });\n\n      test('can be converted into milliseconds', () {\n        expect(15.5.milliseconds, Duration(milliseconds: 15, microseconds: 500));\n      });\n\n      test('can be converted into microseconds', () {\n        expect(10.5.microseconds, Duration(microseconds: 10));\n      });\n\n      test('can be converted into nanoseconds', () {\n        expect(5.5.nanoseconds, Duration(microseconds: 5 ~/ 1000));\n      });\n    });\n\n    group('DateTime', () {\n      test('can subtract Durations', () {\n        expect(\n          DateTime(2019, 1, 1, 0, 0, 30) - 30.seconds,\n          DateTime(2019, 1, 1, 0, 0, 0),\n        );\n      });\n\n      test('can add Durations', () {\n        expect(\n          DateTime(2019, 1, 1, 0, 0, 30) - 30.seconds,\n          DateTime(2019, 1, 1, 0, 0, 0),\n        );\n      });\n\n      group('can get only year, month and day', () {\n        test('when is not utc', () {\n          expect(\n            DateTime(2020, 4, 10, 15, 27, 30).date,\n            DateTime(2020, 4, 10, 0, 0, 0),\n          );\n        });\n\n        test('when is utc', () {\n          expect(\n            DateTime.utc(2020, 4, 10, 15, 27, 30).date,\n            DateTime.utc(2020, 4, 10, 0, 0, 0),\n          );\n        });\n      });\n\n      test('can get only the time', () {\n        expect(\n          /// Returns the time\n          DateTime(2020, 4, 10, 15, 27, 30).timeOfDay,\n          Duration(hours: 15, minutes: 27, seconds: 30),\n        );\n      });\n\n      test('can get complete time with milliseconds and microseconds', () {\n        expect(\n          DateTime(2020, 4, 10, 15, 27, 30, 500, 250).timeOfDay,\n          Duration(hours: 15, minutes: 27, seconds: 30, milliseconds: 500, microseconds: 250),\n        );\n      });\n\n      test('timeOfDay preserves precision when reconstructing DateTime', () {\n        final original = DateTime(2020, 1, 1, 12, 30, 15, 500, 250);\n        final reconstructed = original.date + original.timeOfDay;\n        expect(reconstructed, equals(original));\n      });\n\n      test('can handle isToday', () {\n        final today = date;\n        withClock(Clock.fixed(today), () {\n          final yesterday = today.subtract(Duration(days: 1));\n          final tomorrow = today.add(Duration(days: 1));\n          expect(today.isToday, true);\n          expect(yesterday.isToday, false);\n          expect(tomorrow.isToday, false);\n        });\n      });\n\n      test('can handle isTomorrow', () {\n        final today = date;\n        withClock(Clock.fixed(today), () {\n          final yesterday = today.subtract(Duration(days: 1));\n          final tomorrow = today.add(Duration(days: 1));\n          expect(today.isTomorrow, false);\n          expect(yesterday.isTomorrow, false);\n          expect(tomorrow.isTomorrow, true);\n        });\n      });\n\n      test('can handle wasYesterday', () {\n        final today = date;\n        withClock(Clock.fixed(today), () {\n          final yesterday = today.subtract(Duration(days: 1));\n          final tomorrow = today.add(Duration(days: 1));\n          expect(today.wasYesterday, false);\n          expect(yesterday.wasYesterday, true);\n          expect(tomorrow.wasYesterday, false);\n        });\n      });\n\n      test('can handle isLeapYear', () {\n        expect(DateTime(2020, 10, 10).isLeapYear, true);\n        expect(DateTime(2019, 10, 10).isLeapYear, false);\n        expect(DateTime(2100, 01, 01).isLeapYear, false);\n        expect(DateTime(2000, 01, 01).isLeapYear, true);\n        expect(DateTime(1000, 01, 01).isLeapYear, false);\n        expect(DateTime(1584, 01, 01).isLeapYear, true);\n      });\n\n      test('can handle daysInMonth', () {\n        // Leap year.\n        expect(DateTime(2020, 01, 01).daysInMonth, 31);\n        expect(DateTime(2020, 02, 01).daysInMonth, 29);\n        expect(DateTime(2020, 03, 01).daysInMonth, 31);\n        expect(DateTime(2020, 04, 01).daysInMonth, 30);\n        expect(DateTime(2020, 05, 01).daysInMonth, 31);\n        expect(DateTime(2020, 06, 01).daysInMonth, 30);\n        expect(DateTime(2020, 07, 01).daysInMonth, 31);\n        expect(DateTime(2020, 08, 01).daysInMonth, 31);\n        expect(DateTime(2020, 09, 01).daysInMonth, 30);\n        expect(DateTime(2020, 10, 01).daysInMonth, 31);\n        expect(DateTime(2020, 11, 01).daysInMonth, 30);\n        expect(DateTime(2020, 12, 01).daysInMonth, 31);\n\n        // Non-leap year.\n        expect(DateTime(2019, 01, 01).daysInMonth, 31);\n        expect(DateTime(2019, 02, 01).daysInMonth, 28);\n        expect(DateTime(2019, 03, 01).daysInMonth, 31);\n        expect(DateTime(2019, 04, 01).daysInMonth, 30);\n        expect(DateTime(2019, 05, 01).daysInMonth, 31);\n        expect(DateTime(2019, 06, 01).daysInMonth, 30);\n        expect(DateTime(2019, 07, 01).daysInMonth, 31);\n        expect(DateTime(2019, 08, 01).daysInMonth, 31);\n        expect(DateTime(2019, 09, 01).daysInMonth, 30);\n        expect(DateTime(2019, 10, 01).daysInMonth, 31);\n        expect(DateTime(2019, 11, 01).daysInMonth, 30);\n        expect(DateTime(2019, 12, 01).daysInMonth, 31);\n      });\n\n      test('can handle isAtSameYearAs', () {\n        expect(\n          DateTime(2020, 10, 10).isAtSameYearAs(DateTime(2020, 09, 12)),\n          true,\n        );\n        expect(\n          DateTime(2019, 10, 10).isAtSameYearAs(DateTime(2020, 10, 10)),\n          false,\n        );\n      });\n\n      test('can handle isAtSameMonthAs', () {\n        expect(\n          DateTime(2020, 10, 18).isAtSameMonthAs(DateTime(2020, 10, 12)),\n          true,\n        );\n        expect(\n          DateTime(2020, 09, 10).isAtSameMonthAs(DateTime(2020, 10, 10)),\n          false,\n        );\n        expect(\n          DateTime(2019, 10, 10).isAtSameMonthAs(DateTime(2020, 10, 10)),\n          false,\n        );\n      });\n\n      test('can handle isAtSameDayAs', () {\n        expect(\n          DateTime(2020, 10, 06, 12).isAtSameDayAs(DateTime(2020, 10, 06, 15)),\n          true,\n        );\n        expect(\n          DateTime(2020, 10, 08, 15).isAtSameDayAs(DateTime(2020, 10, 06, 15)),\n          false,\n        );\n        expect(\n          DateTime(2020, 12, 06, 15).isAtSameDayAs(DateTime(2020, 10, 06, 15)),\n          false,\n        );\n        expect(\n          DateTime(2021, 12, 06, 15).isAtSameDayAs(DateTime(2020, 10, 06, 15)),\n          false,\n        );\n      });\n\n      test('can handle isAtSameHourAs', () {\n        expect(\n          DateTime(2020, 10, 06, 12, 15).isAtSameHourAs(\n            DateTime(2020, 10, 06, 12, 25),\n          ),\n          true,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15).isAtSameHourAs(\n            DateTime(2020, 10, 06, 15, 15),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15).isAtSameHourAs(\n            DateTime(2020, 10, 07, 12, 15),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15).isAtSameHourAs(\n            DateTime(2020, 11, 06, 12, 15),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15).isAtSameHourAs(\n            DateTime(2021, 10, 06, 12, 15),\n          ),\n          false,\n        );\n      });\n\n      test('can handle isAtSameMinuteAs', () {\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30).isAtSameMinuteAs(\n            DateTime(2020, 10, 06, 12, 15, 40),\n          ),\n          true,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30).isAtSameMinuteAs(\n            DateTime(2020, 10, 06, 12, 17, 30),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30).isAtSameMinuteAs(\n            DateTime(2020, 10, 06, 15, 15, 30),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30).isAtSameMinuteAs(\n            DateTime(2020, 10, 09, 12, 15, 30),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30).isAtSameMinuteAs(\n            DateTime(2020, 12, 06, 12, 15, 30),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30).isAtSameMinuteAs(\n            DateTime(2022, 10, 06, 12, 15, 30),\n          ),\n          false,\n        );\n      });\n\n      test('can handle isAtSameSecondAs', () {\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 100).isAtSameSecondAs(\n            DateTime(2020, 10, 06, 12, 15, 30, 150),\n          ),\n          true,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 100).isAtSameSecondAs(\n            DateTime(2020, 10, 06, 12, 15, 45, 100),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 100).isAtSameSecondAs(\n            DateTime(2020, 10, 06, 12, 25, 30, 100),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 100).isAtSameSecondAs(\n            DateTime(2020, 10, 06, 17, 15, 30, 100),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 100).isAtSameSecondAs(\n            DateTime(2020, 10, 02, 12, 15, 30, 100),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 100).isAtSameSecondAs(\n            DateTime(2020, 06, 06, 12, 15, 30, 100),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 100).isAtSameSecondAs(\n            DateTime(2016, 10, 06, 12, 15, 30, 100),\n          ),\n          false,\n        );\n      });\n\n      test('can handle isAtSameMillisecondAs', () {\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMillisecondAs(\n            DateTime(2020, 10, 06, 12, 15, 30, 150, 750),\n          ),\n          true,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMillisecondAs(\n            DateTime(2020, 10, 06, 12, 15, 30, 175, 600),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMillisecondAs(\n            DateTime(2020, 10, 06, 12, 15, 32, 150, 600),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMillisecondAs(\n            DateTime(2020, 10, 06, 12, 18, 30, 150, 600),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMillisecondAs(\n            DateTime(2020, 10, 06, 18, 15, 30, 150, 600),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMillisecondAs(\n            DateTime(2020, 10, 09, 12, 15, 30, 150, 600),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMillisecondAs(\n            DateTime(2020, 04, 06, 12, 15, 30, 150, 600),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMillisecondAs(\n            DateTime(1948, 10, 06, 12, 15, 30, 150, 600),\n          ),\n          false,\n        );\n      });\n\n      test('can handle isAtSameMicrosecondAs', () {\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMicrosecondAs(\n            DateTime(2020, 10, 06, 12, 15, 30, 150, 600),\n          ),\n          true,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMicrosecondAs(\n            DateTime(2020, 10, 06, 12, 15, 30, 150, 900),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMicrosecondAs(\n            DateTime(2020, 10, 06, 12, 15, 30, 160, 600),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMicrosecondAs(\n            DateTime(2020, 10, 06, 12, 15, 34, 150, 600),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMicrosecondAs(\n            DateTime(2020, 10, 06, 12, 12, 30, 150, 600),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMicrosecondAs(\n            DateTime(2020, 10, 06, 07, 15, 30, 150, 600),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMicrosecondAs(\n            DateTime(2020, 10, 09, 12, 15, 30, 150, 600),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMicrosecondAs(\n            DateTime(2020, 06, 06, 12, 15, 30, 150, 600),\n          ),\n          false,\n        );\n        expect(\n          DateTime(2020, 10, 06, 12, 15, 30, 150, 600).isAtSameMicrosecondAs(\n            DateTime(2030, 10, 06, 12, 15, 30, 150, 600),\n          ),\n          false,\n        );\n      });\n\n      test('can iterate over DateTimes', () {\n        final start = DateTime(2019);\n        final end = start + 2.days;\n        final days = start.to(end);\n        expect(days.length, 2);\n        expect(days.first, start + 1.days);\n        expect(days.last, end);\n      });\n\n      test('iterating with same dates results in empty iterator', () {\n        expect(DateTime(2019).to(DateTime(2019)), isEmpty);\n      });\n\n      test('can iterate over DateTimes backwards', () {\n        final start = DateTime(2019);\n        final end = start - 2.days;\n        final days = start.to(end);\n        expect(days.length, 2);\n        expect(days.first, start - 1.days);\n        expect(days.last, end);\n      });\n\n      test('can iterate by Duration', () {\n        final start = DateTime(2019);\n        final end = DateTime(2019) + 1.hours;\n        final hours = start.to(end, by: 1.hours);\n        expect(hours.single, end);\n      });\n\n      group('can handle copyWith', () {\n        test('without null values', () {\n          final initial = DateTime(2019, 2, 4, 24, 50, 45, 1, 1);\n          final expected = initial.copyWith(\n            year: 2021,\n            month: 10,\n            day: 28,\n            hour: 12,\n            minute: 45,\n            second: 10,\n            millisecond: 0,\n            microsecond: 12,\n          );\n          expect(expected.year, 2021);\n          expect(expected.month, 10);\n          expect(expected.day, 28);\n          expect(expected.hour, 12);\n          expect(expected.minute, 45);\n          expect(expected.second, 10);\n          expect(expected.millisecond, 0);\n          expect(expected.microsecond, 12);\n        });\n\n        test('with null values', () {\n          final initial = DateTime(2019, 2, 4, 24, 50, 45, 1, 1);\n          final year = initial.copyWith(year: 2021);\n          expect(year.year, 2021);\n          final month = initial.copyWith(month: 10);\n          expect(month.month, 10);\n          final day = initial.copyWith(day: 28);\n          expect(day.day, 28);\n          final hour = initial.copyWith(hour: 12);\n          expect(hour.hour, 12);\n          final minute = initial.copyWith(minute: 45);\n          expect(minute.minute, 45);\n          final second = initial.copyWith(second: 10);\n          expect(second.second, 10);\n          final millisecond = initial.copyWith(millisecond: 0);\n          expect(millisecond.millisecond, 0);\n          final microsecond = initial.copyWith(microsecond: 12);\n          expect(microsecond.microsecond, 12);\n        });\n\n        test('copyWith should save isUtc', () async {\n          final now = DateTime.now().toUtc();\n          expect(now.isUtc, isTrue);\n\n          final later = now.copyWith(hour: now.hour + 3);\n          expect(later.isUtc, isTrue);\n        });\n      });\n\n      group('can get first/last days', () {\n        test('first day of week', () {\n          final initial = DateTime(2022, 5, 20);\n          final expected = DateTime(2022, 5, 16);\n          expect(initial.firstDayOfWeek, expected);\n        });\n\n        test('last day of week', () {\n          final initial = DateTime(2022, 5, 20);\n          final expected = DateTime(2022, 5, 22);\n          expect(initial.lastDayOfWeek, expected);\n        });\n\n        test('first day of month', () {\n          final initial = DateTime(2022, 5, 20);\n          final expected = DateTime(2022, 5, 1);\n          expect(initial.firstDayOfMonth, expected);\n        });\n\n        group('last day of month', () {\n          test('last day of month', () {\n            final initial = DateTime(2022, 5, 20);\n            final expected = DateTime(2022, 5, 31);\n            expect(initial.lastDayOfMonth, expected);\n          });\n          test('february not leap year', () {\n            final initial = DateTime(2022, 2, 20);\n            final expected = DateTime(2022, 2, 28);\n            expect(initial.lastDayOfMonth, expected);\n          });\n\n          test('february leap year', () {\n            final initial = DateTime(2020, 2, 20);\n            final expected = DateTime(2020, 2, 29);\n            expect(initial.lastDayOfMonth, expected);\n          });\n        });\n\n        test('first day of year', () {\n          final initial = DateTime(2022, 5, 20);\n          final expected = DateTime(2022, 1, 1);\n          expect(initial.firstDayOfYear, expected);\n        });\n\n        test('last day of year', () {\n          final initial = DateTime(2022, 5, 20);\n          final expected = DateTime(2022, 12, 31);\n          expect(initial.lastDayOfYear, expected);\n        });\n      });\n    });\n\n    group('clamp', () {\n      group('returns max when before it', () {\n        final it = DateTime(2022, DateTime.october, 15);\n        final min = DateTime(2022, DateTime.september, 1);\n        final max = DateTime(2022, DateTime.september, 30);\n\n        test('when it has a value for min', () {\n          expect(it.clamp(min: min, max: max), equals(max));\n        });\n\n        test('when it does not have a value for min', () {\n          expect(it.clamp(max: max), equals(max));\n        });\n      });\n\n      group('returns min when after it', () {\n        final it = DateTime(2022, DateTime.august, 21);\n        final min = DateTime(2022, DateTime.september, 15);\n        final max = DateTime(2022, DateTime.september, 30);\n\n        test('when it has a value for max', () {\n          expect(it.clamp(min: min, max: max), equals(min));\n        });\n\n        test('when it does not have a value for max', () {\n          expect(it.clamp(min: min), equals(min));\n        });\n      });\n\n      group('returns it', () {\n        final it = DateTime(2022, DateTime.september, 1);\n        final min = DateTime(2022, DateTime.august, 1);\n        final max = DateTime(2022, DateTime.september, 30);\n\n        test('when both min and max are null', () {\n          expect(it.clamp(), equals(it));\n        });\n\n        test('when is longer than min and max is null', () {\n          expect(it.clamp(min: min), equals(it));\n        });\n\n        test('when is shorter than max and min is null', () {\n          expect(it.clamp(max: max), equals(it));\n        });\n\n        test('when is longer than min and shorter than max', () {\n          expect(it.clamp(min: min, max: max), equals(it));\n        });\n      });\n\n      test('asserts that min should be before max', () {\n        final it = DateTime(2022, DateTime.september, 1);\n        final min = DateTime(2022, DateTime.september, 30);\n        final max = DateTime(2022, DateTime.august, 1);\n        expect(\n          () => it.clamp(min: min, max: max),\n          throwsA(isA<AssertionError>()),\n        );\n      });\n\n      test('returns min/max if are equal', () {\n        final it = DateTime(2022, DateTime.september, 1);\n        final min = DateTime(2022, DateTime.september, 30);\n        final max = min;\n        expect(it.clamp(min: min, max: max), min);\n      });\n    });\n    group('Weekend', () {\n      test('monday is not weekend', () {\n        final it = DateTime(2022, DateTime.august, 1);\n        expect(it.isWeekend, isFalse);\n      });\n      test('tuesday is not weekend', () {\n        final it = DateTime(2022, DateTime.august, 2);\n        expect(it.isWeekend, isFalse);\n      });\n      test('wednesday is not weekend', () {\n        final it = DateTime(2022, DateTime.august, 3);\n        expect(it.isWeekend, isFalse);\n      });\n      test('thursday is not weekend', () {\n        final it = DateTime(2022, DateTime.august, 4);\n        expect(it.isWeekend, isFalse);\n      });\n      test('friday is not weekend', () {\n        final it = DateTime(2022, DateTime.august, 5);\n        expect(it.isWeekend, isFalse);\n      });\n      test('saturday is weekend', () {\n        final it = DateTime(2022, DateTime.august, 6);\n        expect(it.isWeekend, isTrue);\n      });\n      test('sunday is weekend', () {\n        final it = DateTime(2022, DateTime.august, 7);\n        expect(it.isWeekend, isTrue);\n      });\n    });\n    group('Workday', () {\n      test('monday is workday', () {\n        final it = DateTime(2022, DateTime.august, 1);\n        expect(it.isWorkday, isTrue);\n      });\n      test('tuesday is workday', () {\n        final it = DateTime(2022, DateTime.august, 2);\n        expect(it.isWorkday, isTrue);\n      });\n      test('wednesday is workday', () {\n        final it = DateTime(2022, DateTime.august, 3);\n        expect(it.isWorkday, isTrue);\n      });\n      test('thursday is workday', () {\n        final it = DateTime(2022, DateTime.august, 4);\n        expect(it.isWorkday, isTrue);\n      });\n      test('friday is workday', () {\n        final it = DateTime(2022, DateTime.august, 5);\n        expect(it.isWorkday, isTrue);\n      });\n      test('saturday is not workday', () {\n        final it = DateTime(2022, DateTime.august, 6);\n        expect(it.isWorkday, isFalse);\n      });\n      test('sunday is not workday', () {\n        final it = DateTime(2022, DateTime.august, 7);\n        expect(it.isWorkday, isFalse);\n      });\n    });\n    group('EndOfDay', () {\n      test('returns the last microsecond of the day', () {\n        final it = DateTime(2022, DateTime.august, 1, 12, 30, 15, 10, 5);\n        final expected = DateTime(2022, DateTime.august, 1, 23, 59, 59, 999, 999);\n        expect(it.endOfDay, expected);\n      });\n      test('returns the last microsecond of the day for utc', () {\n        final it = DateTime.utc(2022, DateTime.august, 1, 12, 30, 15, 10, 5);\n        final expected = DateTime.utc(2022, DateTime.august, 1, 23, 59, 59, 999, 999);\n        expect(it.endOfDay, expected);\n      });\n    });\n    group('Shift', () {\n      group('empty parameters', () {\n        test('local', () {\n          final it = DateTime(2024, DateTime.january, 3, 2, 24, 12, 123, 456);\n          expect(it.shift(), it);\n        });\n        test('utc', () {\n          final it = DateTime.utc(2024, DateTime.january, 3, 2, 24, 12, 123, 456);\n          expect(it.shift(), it);\n        });\n      });\n      group('adding parameters', () {\n        final it = DateTime(2000, 1, 1, 1, 1, 1, 1, 1);\n        test('can shift years', () {\n          expect(it.shift(years: 1), DateTime(2001, 1, 1, 1, 1, 1, 1, 1));\n        });\n        test('can shift months', () {\n          expect(it.shift(months: 1), DateTime(2000, 2, 1, 1, 1, 1, 1, 1));\n        });\n        test('can shift days', () {\n          expect(it.shift(days: 1), DateTime(2000, 1, 2, 1, 1, 1, 1, 1));\n        });\n        test('can shift hours', () {\n          expect(it.shift(hours: 1), DateTime(2000, 1, 1, 2, 1, 1, 1, 1));\n        });\n        test('can shift minutes', () {\n          expect(it.shift(minutes: 1), DateTime(2000, 1, 1, 1, 2, 1, 1, 1));\n        });\n        test('can shift seconds', () {\n          expect(it.shift(seconds: 1), DateTime(2000, 1, 1, 1, 1, 2, 1, 1));\n        });\n        test('can shift milliseconds', () {\n          expect(it.shift(milliseconds: 1), DateTime(2000, 1, 1, 1, 1, 1, 2, 1));\n        });\n        test('can shift microseconds', () {\n          expect(it.shift(microseconds: 1), DateTime(2000, 1, 1, 1, 1, 1, 1, 2));\n        });\n      });\n      group('subtracting parameters', () {\n        final it = DateTime(2000, 1, 1, 1, 1, 1, 1, 1);\n        test('can shift years', () {\n          expect(it.shift(years: -1), DateTime(1999, 1, 1, 1, 1, 1, 1, 1));\n        });\n        test('can shift months', () {\n          expect(it.shift(months: -1), DateTime(1999, 12, 1, 1, 1, 1, 1, 1));\n        });\n        test('can shift days', () {\n          expect(it.shift(days: -1), DateTime(1999, 12, 31, 1, 1, 1, 1, 1));\n        });\n        test('can shift hours', () {\n          expect(it.shift(hours: -1), DateTime(2000, 1, 1, 0, 1, 1, 1, 1));\n        });\n        test('can shift minutes', () {\n          expect(it.shift(minutes: -1), DateTime(2000, 1, 1, 1, 0, 1, 1, 1));\n        });\n        test('can shift seconds', () {\n          expect(it.shift(seconds: -1), DateTime(2000, 1, 1, 1, 1, 0, 1, 1));\n        });\n        test('can shift milliseconds', () {\n          expect(it.shift(milliseconds: -1), DateTime(2000, 1, 1, 1, 1, 1, 0, 1));\n        });\n        test('can shift microseconds', () {\n          expect(it.shift(microseconds: -1), DateTime(2000, 1, 1, 1, 1, 1, 1, 0));\n        });\n      });\n      group('overflow', () {\n        group('months', () {\n          test('adding', () {\n            final it = DateTime(2023, 11);\n            expect(it.shift(months: 2), DateTime(2024));\n          });\n          test('subtracting', () {\n            final it = DateTime(2023);\n            expect(it.shift(months: -2), DateTime(2022, 11));\n          });\n        });\n        group('days', () {\n          test('adding', () {\n            final it = DateTime(2023, 2, 27);\n            expect(it.shift(days: 2), DateTime(2023, 3, 1));\n          });\n          test('subtracting', () {\n            final it = DateTime(2023, 2, 1);\n            expect(it.shift(days: -2), DateTime(2023, 1, 30));\n          });\n        });\n        group('hours', () {\n          test('adding', () {\n            final it = DateTime(2023, 2, 1, 23);\n            expect(it.shift(hours: 2), DateTime(2023, 2, 2, 1));\n          });\n          test('subtracting', () {\n            final it = DateTime(2023, 2, 2, 1);\n            expect(it.shift(hours: -2), DateTime(2023, 2, 1, 23));\n          });\n        });\n        group('minutes', () {\n          test('adding', () {\n            final it = DateTime(2023, 2, 1, 1, 59);\n            expect(it.shift(minutes: 2), DateTime(2023, 2, 1, 2, 1));\n          });\n          test('subtracting', () {\n            final it = DateTime(2023, 2, 1, 1);\n            expect(it.shift(minutes: -2), DateTime(2023, 2, 1, 0, 58));\n          });\n        });\n        group('seconds', () {\n          test('adding', () {\n            final it = DateTime(2023, 2, 1, 1, 1, 59);\n            expect(it.shift(seconds: 2), DateTime(2023, 2, 1, 1, 2, 1));\n          });\n          test('subtracting', () {\n            final it = DateTime(2023, 2, 1, 1, 1);\n            expect(it.shift(seconds: -2), DateTime(2023, 2, 1, 1, 0, 58));\n          });\n        });\n        group('milliseconds', () {\n          test('adding', () {\n            final it = DateTime(2023, 2, 1, 1, 1, 1, 999);\n            expect(it.shift(milliseconds: 2), DateTime(2023, 2, 1, 1, 1, 2, 1));\n          });\n          test('subtracting', () {\n            final it = DateTime(2023, 2, 1, 1, 1, 1, 1);\n            expect(it.shift(milliseconds: -2), DateTime(2023, 2, 1, 1, 1, 0, 999));\n          });\n        });\n        group('microseconds', () {\n          test('adding', () {\n            final it = DateTime(2023, 2, 1, 1, 1, 1, 1, 999);\n            expect(it.shift(microseconds: 2), DateTime(2023, 2, 1, 1, 1, 1, 2, 1));\n          });\n          test('subtracting', () {\n            final it = DateTime(2023, 2, 1, 1, 1, 1, 1, 1);\n            expect(it.shift(microseconds: -2), DateTime(2023, 2, 1, 1, 1, 1, 0, 999));\n          });\n        });\n      });\n    });\n  });\n\n  group('Duration', () {\n    test('has correct days-to-week static value', () {\n      expect(DurationTimeExtension.daysPerWeek, 7);\n    });\n\n    test('has correct nanosecond-to-microsecond static value', () {\n      expect(DurationTimeExtension.nanosecondsPerMicrosecond, 1000);\n    });\n\n    test('can be converted to weeks', () {\n      expect(7.days.inWeeks, 1);\n    });\n\n    test('can be converted into a future DateTime', () {\n      withClock(Clock.fixed(date), () {\n        expect(7.days.fromNow, date + 7.days);\n      });\n    });\n\n    test('can be converted into a previous DateTime', () {\n      withClock(Clock.fixed(date), () {\n        expect(7.days.ago, date - 7.days);\n      });\n    });\n\n    test('Can be used to pause the program flow', () async {\n      final timeToWait = Duration(seconds: 2);\n      final before = DateTime.now();\n      await timeToWait.delay;\n      final after = DateTime.now();\n      final extraTime = after.millisecondsSinceEpoch - before.add(timeToWait).millisecondsSinceEpoch;\n      expect(extraTime >= 0, true);\n    });\n\n    group('clamp', () {\n      group('returns max when shorter than it', () {\n        final it = Duration(days: 10, hours: 12);\n        final min = Duration(days: 5);\n        final max = Duration(days: 10);\n\n        test('when it has a value for min', () {\n          expect(it.clamp(min: min, max: max), equals(max));\n        });\n\n        test('when it does not have a value for min', () {\n          expect(it.clamp(max: max), equals(max));\n        });\n      });\n\n      group('returns min when longer than it', () {\n        final it = Duration(hours: 18);\n        final min = Duration(days: 5);\n        final max = Duration(days: 10);\n\n        test('when it has a value for max', () {\n          expect(it.clamp(min: min, max: max), equals(min));\n        });\n\n        test('when it does not have a value for max', () {\n          expect(it.clamp(min: min), equals(min));\n        });\n      });\n\n      group('returns it', () {\n        final it = Duration(days: 0);\n        final min = Duration(days: -5);\n        final max = Duration(days: 5);\n\n        test('when both min and max are null', () {\n          expect(it.clamp(), equals(it));\n        });\n\n        test('when is longer than min and max is null', () {\n          expect(it.clamp(min: min), equals(it));\n        });\n\n        test('when is shorter than max and min is null', () {\n          expect(it.clamp(max: max), equals(it));\n        });\n\n        test('when is longer than min and shorter than max', () {\n          expect(it.clamp(min: min, max: max), equals(it));\n        });\n      });\n\n      test('asserts that min should be shorter than max', () {\n        final it = Duration(days: -0);\n        final min = Duration(days: 5);\n        final max = Duration(days: -5);\n        expect(\n          () => it.clamp(min: min, max: max),\n          throwsA(isA<AssertionError>()),\n        );\n      });\n\n      test('returns min/max if are equal', () {\n        final it = Duration(days: -0);\n        final min = Duration(days: 5);\n        final max = min;\n        expect(it.clamp(min: min, max: max), min);\n      });\n    });\n  });\n}\n"
  }
]