Skip to content

Commit

Permalink
fixes time of day
Browse files Browse the repository at this point in the history
  • Loading branch information
FMorschel committed Nov 19, 2024
1 parent 2f82c22 commit 8737e4d
Show file tree
Hide file tree
Showing 22 changed files with 133 additions and 37 deletions.
1 change: 1 addition & 0 deletions lib/due_date.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export 'src/date_validators/date_validators.dart';
export 'src/due_date.dart';
export 'src/enums/enums.dart' show Month, Week, Weekday, WeekdayOccurrence;
export 'src/everies/everies.dart';
export 'src/extensions/extensions.dart' show ExactTimeOfDay, WorkdayInMonth;
export 'src/extensions/extensions.dart'
show
AddDays,
Expand Down
1 change: 1 addition & 0 deletions lib/period.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ import 'src/periods/periods.dart';

export 'src/enums/enums.dart' show Month, PeriodGenerator, Week, Weekday;
export 'src/everies/everies.dart';
export 'src/extensions/extensions.dart' show ExactTimeOfDay;
export 'src/period_generators/period_generators.dart';
export 'src/periods/periods.dart';
3 changes: 2 additions & 1 deletion lib/src/date_validators/date_validator_time_of_day.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:equatable/equatable.dart';
import 'package:time/time.dart';

import '../extensions/extensions.dart';
import 'date_validator.dart';
import 'date_validator_mixin.dart';

Expand Down Expand Up @@ -34,7 +35,7 @@ class DateValidatorTimeOfDay extends DateValidator

@override
bool valid(DateTime date) {
return date.timeOfDay == timeOfDay;
return date.exactTimeOfDay == timeOfDay;
}

@override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:equatable/equatable.dart';
import 'package:time/time.dart';

import '../enums/enums.dart';
import '../extensions/extensions.dart';
import 'date_validator.dart';
import 'date_validator_mixin.dart';

Expand Down Expand Up @@ -49,7 +49,7 @@ class DateValidatorWeekdayCountInMonth extends DateValidator
day: day,
utc: date.isUtc,
);
return valid.add(date.timeOfDay) == date;
return valid.add(date.exactTimeOfDay) == date;
}

@override
Expand Down
4 changes: 3 additions & 1 deletion lib/src/due_date.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:clock/clock.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
import 'package:time/time.dart';
Expand Down Expand Up @@ -173,7 +174,7 @@ class DueDateTime<T extends Every> extends DateTime with EquatableMixin {
/// The limit for the operations.
DateTime? limit,
}) {
final now = DateTime.now();
final now = _clock.now();
return DueDateTime.fromDate(
now,
every: EveryDueDayMonth(now.day) as T,
Expand Down Expand Up @@ -224,6 +225,7 @@ class DueDateTime<T extends Every> extends DateTime with EquatableMixin {
}

static const _week = Duration(days: DateTime.daysPerWeek);
static const _clock = Clock();

/// The handler for processing the next dates.
final T every;
Expand Down
7 changes: 4 additions & 3 deletions lib/src/enums/weekday.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:time/time.dart';
import '../date_validators/date_validators.dart';
import '../everies/everies.dart';
import '../extensions/extensions.dart';
import '../period_generators/period_generators.dart';
import '../periods/periods.dart';

Expand Down Expand Up @@ -105,7 +106,7 @@ enum Weekday implements Comparable<Weekday> {
if (date.weekday == dateTimeValue) {
count++;
}
date = date.add(const Duration(days: 1));
date = date.addDays(1);
} while (date.month == month);
return count;
}
Expand All @@ -115,8 +116,8 @@ enum Weekday implements Comparable<Weekday> {
final monday = date.firstDayOfWeek;
final result = monday.add(Duration(days: index));
return date.isUtc
? result.toUtc().date.add(date.timeOfDay)
: result.date.add(date.timeOfDay);
? result.toUtc().date.add(date.exactTimeOfDay)
: result.date.add(date.exactTimeOfDay);
}

@override
Expand Down
6 changes: 3 additions & 3 deletions lib/src/everies/every_due_day_month.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:time/time.dart';

import '../date_validators/date_validators.dart';
import '../extensions/extensions.dart';
import 'every_date_validator.dart';
import 'every_month.dart';

Expand Down Expand Up @@ -62,14 +63,13 @@ class EveryDueDayMonth extends DateValidatorDueDayMonth
if (!valid(localDate)) {
if (localMonths.isNegative) {
if (localDate.day < dueDay) {
localDate =
localDate.firstDayOfMonth.subtract(const Duration(days: 1));
localDate = localDate.firstDayOfMonth.subtractDays(1);
}
localDate = _thisMonthsDay(localDate);
localMonths++;
} else {
if (localDate.day > dueDay) {
localDate = localDate.lastDayOfMonth.add(const Duration(days: 1));
localDate = localDate.lastDayOfMonth.addDays(1);
}
localDate = _thisMonthsDay(localDate);
localMonths--;
Expand Down
4 changes: 2 additions & 2 deletions lib/src/everies/every_due_time_of_day.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ class EveryDueTimeOfDay extends DateValidatorTimeOfDay

/// Constructor that takes the time of day from [date].
factory EveryDueTimeOfDay.from(DateTime date) {
return EveryDueTimeOfDay(date.timeOfDay);
return EveryDueTimeOfDay(date.exactTimeOfDay);
}

@override
DateTime startDate(DateTime date) {
if (date.timeOfDay <= timeOfDay) {
if (date.exactTimeOfDay <= timeOfDay) {
return date.date.add(timeOfDay);
} else {
return next(date);
Expand Down
20 changes: 10 additions & 10 deletions lib/src/everies/every_weekday.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:time/time.dart';

import '../date_validators/date_validators.dart';
import '../enums/enums.dart';
import '../extensions/extensions.dart';
import 'every_date_validator.dart';
import 'every_date_validator_union.dart';
import 'every_month.dart';
Expand Down Expand Up @@ -52,8 +53,7 @@ class EveryWeekday extends DateValidatorWeekday
if (date.weekday < weekday.dateTimeValue) {
return weekday.fromWeekOf(date);
} else {
return weekday
.fromWeekOf(date.lastDayOfWeek.add(const Duration(days: 1)));
return weekday.fromWeekOf(date.lastDayOfWeek.addDays(1));
}
}

Expand All @@ -66,8 +66,7 @@ class EveryWeekday extends DateValidatorWeekday
if (date.weekday > weekday.dateTimeValue) {
return weekday.fromWeekOf(date);
} else {
return weekday
.fromWeekOf(date.firstDayOfWeek.subtract(const Duration(days: 1)));
return weekday.fromWeekOf(date.firstDayOfWeek.subtractDays(1));
}
}

Expand All @@ -81,20 +80,19 @@ class EveryWeekday extends DateValidatorWeekday
if (!valid(localDate)) {
if (localWeeks.isNegative) {
if (localDate.weekday < weekday.dateTimeValue) {
localDate =
localDate.firstDayOfWeek.subtract(const Duration(days: 1));
localDate = localDate.firstDayOfWeek.subtractDays(1);
}
localDate = weekday.fromWeekOf(localDate);
localWeeks++;
} else {
if (localDate.weekday > weekday.dateTimeValue) {
localDate = localDate.lastDayOfWeek.add(const Duration(days: 1));
localDate = localDate.lastDayOfWeek.addDays(1);
}
localDate = weekday.fromWeekOf(localDate);
localWeeks--;
}
}
final day = localDate.toUtc().add(Duration(days: localWeeks * 7));
final day = localDate.toUtc().addDays(localWeeks * 7);
return _solveFor(localDate, day);
}

Expand All @@ -118,7 +116,9 @@ class EveryWeekday extends DateValidatorWeekday

/// Solves the date for the given [date] and [day].
DateTime _solveFor(DateTime date, DateTime day) {
if (date.isUtc) return weekday.fromWeekOf(day.date).add(date.timeOfDay);
return weekday.fromWeekOf(day.toLocal().date).add(date.timeOfDay);
if (date.isUtc) {
return weekday.fromWeekOf(day.date).add(date.exactTimeOfDay);
}
return weekday.fromWeekOf(day.toLocal().date).add(date.exactTimeOfDay);
}
}
11 changes: 11 additions & 0 deletions lib/src/extensions/exact_time_of_day.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/// Extension on [DateTime] to get the exact time of the day.
extension ExactTimeOfDay on DateTime {
/// Returns the exact time of the day.
Duration get exactTimeOfDay => Duration(
hours: hour,
minutes: minute,
seconds: second,
milliseconds: millisecond,
microseconds: microsecond,
);
}
2 changes: 2 additions & 0 deletions lib/src/extensions/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ export 'clamp_in_month.dart';
export 'date_validator_list_ext.dart';
export 'day_in_year.dart';
export 'every_date_validator_list_ext.dart';
export 'exact_time_of_day.dart';
export 'previous_next.dart';
export 'week_calc.dart';
export 'workday_in_month.dart';
16 changes: 16 additions & 0 deletions lib/src/extensions/workday_in_month.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import '../helpers/helpers.dart';

/// Extension methods to get the workday number in the month of a [DateTime].
extension WorkdayInMonth on DateTime {
// ignore: format-comment, false positive
/// Returns the workday number in the month of this [DateTime].
///
/// If the [DateTime] is not a workday (weekend: saturday or sunday), returns
/// 0.
int get workdayInMonth => WorkdayHelper.getWorkdayNumberInMonth(this);

// ignore: format-comment, false positive
/// Returns `true` if the [DateTime] is a workday (weekdays: monday to
/// friday).
bool get isWorkday => WorkdayHelper.every.valid(this);
}
4 changes: 2 additions & 2 deletions lib/src/period_generators/week_generator.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:equatable/equatable.dart';
import 'package:time/time.dart';
import '../extensions/extensions.dart';
import '../periods/periods.dart';
import 'period_generator_mixin.dart';

Expand All @@ -17,8 +18,7 @@ class WeekGenerator with PeriodGeneratorMixin<WeekPeriod>, EquatableMixin {
if (difference > 0) difference -= DateTime.daysPerWeek;
final day = date.day + difference;
final start = date.copyWith(day: day).date;
final end =
start.add(const Duration(days: DateTime.daysPerWeek - 1)).endOfDay;
final end = start.addDays(DateTime.daysPerWeek - 1).endOfDay;
return WeekPeriod(start: start, end: end);
}

Expand Down
5 changes: 3 additions & 2 deletions lib/src/periods/fortnight_period.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:time/time.dart';
import '../extensions/extensions.dart';
import '../period_generators/period_generators.dart';
import 'day_period.dart';
import 'day_period_bundle.dart';
Expand Down Expand Up @@ -31,8 +32,8 @@ class FortnightPeriod extends Period implements DayPeriodBundle {
milliseconds: 999,
microseconds: 999,
)) ||
(start.timeOfDay != Duration.zero) ||
(end.timeOfDay != end.endOfDay.timeOfDay) ||
(start.exactTimeOfDay != Duration.zero) ||
(end.exactTimeOfDay != end.endOfDay.exactTimeOfDay) ||
!start.isAtSameMonthAs(end) ||
((start.firstDayOfMonth != start) &&
(start != start.copyWith(day: 16))) ||
Expand Down
5 changes: 3 additions & 2 deletions lib/src/periods/month_period.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:time/time.dart';
import '../extensions/extensions.dart';
import '../period_generators/period_generators.dart';
import 'day_period.dart';
import 'day_period_bundle.dart';
Expand All @@ -24,8 +25,8 @@ class MonthPeriod extends Period implements DayPeriodBundle {
const microsecond = Duration(microseconds: 1);
if (!start.isAtSameMonthAs(end) ||
end.add(microsecond).isAtSameMonthAs(start) ||
(start.timeOfDay != Duration.zero) ||
(end.timeOfDay != end.endOfDay.timeOfDay) ||
(start.exactTimeOfDay != Duration.zero) ||
(end.exactTimeOfDay != end.endOfDay.exactTimeOfDay) ||
(start.day != 1) ||
(end.day != end.lastDayOfMonth.day)) {
throw ArgumentError.value(
Expand Down
5 changes: 3 additions & 2 deletions lib/src/periods/semester_period.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:time/time.dart';
import '../extensions/extensions.dart';
import '../period_generators/month_generator.dart';
import '../period_generators/period_generators.dart';
import 'month_period.dart';
Expand All @@ -22,8 +23,8 @@ class SemesterPeriod extends Period implements MonthPeriodBundle {
'The difference between start and end must be 183 days, 23 hours, '
'59 minutes, 59 seconds, 999 milliseconds and 999 microseconds',
) {
if ((start.timeOfDay != Duration.zero) ||
(end.timeOfDay != end.endOfDay.timeOfDay) ||
if ((start.exactTimeOfDay != Duration.zero) ||
(end.exactTimeOfDay != end.endOfDay.exactTimeOfDay) ||
start.isAtSameMonthAs(end) ||
(start.firstDayOfMonth != start) ||
(end.lastDayOfMonth.endOfDay != end) ||
Expand Down
5 changes: 3 additions & 2 deletions lib/src/periods/trimester_period.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:time/time.dart';
import '../extensions/extensions.dart';
import '../period_generators/month_generator.dart';
import '../period_generators/period_generators.dart';
import 'month_period.dart';
Expand All @@ -22,8 +23,8 @@ class TrimesterPeriod extends Period implements MonthPeriodBundle {
'The difference between start and end must be 91 days, 23 hours, '
'59 minutes, 59 seconds, 999 milliseconds and 999 microseconds',
) {
if ((start.timeOfDay != Duration.zero) ||
(end.timeOfDay != end.endOfDay.timeOfDay) ||
if ((start.exactTimeOfDay != Duration.zero) ||
(end.exactTimeOfDay != end.endOfDay.exactTimeOfDay) ||
start.isAtSameMonthAs(end) ||
(start.firstDayOfMonth != start) ||
(end.lastDayOfMonth.endOfDay != end) ||
Expand Down
5 changes: 3 additions & 2 deletions lib/src/periods/week_period.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:time/time.dart';
import '../enums/enums.dart';
import '../extensions/extensions.dart';
import '../period_generators/period_generators.dart';
import 'day_period.dart';
import 'day_period_bundle.dart';
Expand Down Expand Up @@ -31,8 +32,8 @@ class WeekPeriod extends Period implements DayPeriodBundle {
milliseconds: 999,
microseconds: 999,
)) ||
(start.timeOfDay != Duration.zero) ||
(end.timeOfDay != end.endOfDay.timeOfDay) ||
(start.exactTimeOfDay != Duration.zero) ||
(end.exactTimeOfDay != end.endOfDay.exactTimeOfDay) ||
(end.weekday != Weekday.from(start).previous.dateTimeValue)) {
throw ArgumentError.value(
end,
Expand Down
5 changes: 3 additions & 2 deletions lib/src/periods/year_period.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:time/time.dart';
import '../extensions/extensions.dart';
import '../period_generators/month_generator.dart';
import '../period_generators/period_generators.dart';
import 'month_period.dart';
Expand All @@ -25,8 +26,8 @@ class YearPeriod extends Period implements MonthPeriodBundle {
const microsecond = Duration(microseconds: 1);
if (!start.isAtSameYearAs(end) ||
end.add(microsecond).isAtSameYearAs(start) ||
(start.timeOfDay != Duration.zero) ||
(end.timeOfDay != end.endOfDay.timeOfDay) ||
(start.exactTimeOfDay != Duration.zero) ||
(end.exactTimeOfDay != end.endOfDay.exactTimeOfDay) ||
start.isAtSameMonthAs(end) ||
(start.firstDayOfMonth != start) ||
(end.lastDayOfMonth.endOfDay != end) ||
Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ environment:
sdk: '>=2.17.6 <4.0.0'

dependencies:
clock: ^1.1.2
collection: '>=1.16.0 <2.0.0'
equatable: '>=2.0.5 <3.0.0'
meta: ^1.11.0
Expand Down
5 changes: 4 additions & 1 deletion test/due_date_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:clock/clock.dart';
import 'package:due_date/due_date.dart';
import 'package:test/test.dart';

Expand Down Expand Up @@ -75,7 +76,9 @@ void main() {
});
});
test('Now', () {
expect(DueDateTime.now(), equals(DateTime.now()));
withClock(Clock.fixed(DateTime.now()), () {
expect(DueDateTime.now(), equals(DateTime.now()));
});
});
group('FromDate:', () {
final matcher = DateTime.utc(year, 2, 28);
Expand Down
Loading

0 comments on commit 8737e4d

Please sign in to comment.