Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ linter:
- always_specify_types
- annotate_overrides
# - avoid_annotating_with_dynamic # conflicts with always_specify_types
- avoid_as
# - avoid_as
# - avoid_bool_literals_in_conditional_expressions # not yet tested
# - avoid_catches_without_on_clauses # we do this commonly
# - avoid_catching_errors # we do this commonly
Expand Down
2 changes: 1 addition & 1 deletion example/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ void main() {

final List<GregorianCalendar> days = GregorianCalendar.getWeekdaysFromWeek(
new GregorianCalendar(2018, 2, 24),
new WeekdayMask.fromIterable(<int>[7, 2, 4, 5]));
new WeekdayMask.fromIterable(<int>[7, 2, 4, 5]))!;
print(days);
// print(d);
// for (var day in new MonthIterable(
Expand Down
41 changes: 18 additions & 23 deletions lib/src/calendar_iterators.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,6 @@ abstract class CalendarIterableBase<TCal extends Calendar>
/// Generic iterator for advancing a date
class CalendarIterator<TCal extends Calendar> implements Iterator<TCal> {
CalendarIterator(this._start, this._end, this._increment, this._incrementer) {
if (_incrementer == null) {
throw new ArgumentError.notNull('_incrementer');
}

if (_increment == null) {
throw new ArgumentError.notNull('_increment');
}
if (_increment == 0) {
throw new ArgumentError.value(
_increment, 'CalendarIterator', 'Increment must not be 0');
Expand All @@ -33,60 +26,62 @@ class CalendarIterator<TCal extends Calendar> implements Iterator<TCal> {
_nextDate = _start;
}

final TCal _start;
final TCal _end;
final TCal? _start;
final TCal? _end;
final int _increment;
TCal _current;
TCal _nextDate;
TCal? _current;
TCal? _nextDate;
final CalendarIteratorIncrementer<TCal> _incrementer;

// Iterator contract for current allows us to do a null check because clients
// must first check moveNext and get true before calling current.
@override
TCal get current => _current;
TCal get current => _current!;

@override
bool moveNext() {
if (_current == null || _start == null) {
return false;
}
_current = _nextDate.copy();
_nextDate = _incrementer(_current, _increment);
_current = _nextDate!.copy() as TCal?;
_nextDate = _incrementer(_current!, _increment);

return _end == null || _current.compareTo(_end) <= 0;
return _end == null || _current!.compareTo(_end!) <= 0;
}
}

/// An iterable range of days
class DayRange<TCal extends Calendar> extends CalendarIterableBase<TCal> {
DayRange(Calendar start, Calendar end, {int increment = 1})
DayRange(TCal start, TCal end, {int increment = 1})
: super(start, end, increment: increment);
@override
Iterator<TCal> get iterator => new CalendarIterator<TCal>(
start, end, increment, (TCal curr, int inc) => curr.addDays(inc));
start, end, increment, (TCal curr, int inc) => curr.addDays(inc) as TCal);
}

/// An iterable range of weeks
class WeekRange<TCal extends Calendar> extends CalendarIterableBase<TCal> {
WeekRange(Calendar start, Calendar end, {int increment = 1})
WeekRange(TCal start, TCal end, {int increment = 1})
: super(start, end, increment: increment);
@override
Iterator<TCal> get iterator => new CalendarIterator<TCal>(
start, end, increment, (TCal curr, int inc) => curr.addWeeks(inc));
start, end, increment, (TCal curr, int inc) => curr.addWeeks(inc) as TCal);
}

/// An iterable range of months
class MonthRange<TCal extends Calendar> extends CalendarIterableBase<TCal> {
MonthRange(Calendar start, Calendar end, {int increment = 1})
MonthRange(TCal start, TCal end, {int increment = 1})
: super(start, end, increment: increment);
@override
Iterator<TCal> get iterator => new CalendarIterator<TCal>(
start, end, increment, (TCal curr, int inc) => curr.addMonths(inc));
start, end, increment, (TCal curr, int inc) => curr.addMonths(inc) as TCal);
}

/// An iterable range of years
class YearRange<TCal extends Calendar> extends CalendarIterableBase<TCal> {
YearRange(Calendar start, Calendar end, {int increment = 1})
YearRange(TCal start, TCal end, {int increment = 1})
: super(start, end, increment: increment);
@override
Iterator<TCal> get iterator => new CalendarIterator<TCal>(
start, end, increment, (TCal curr, int inc) => curr.addYears(inc));
start, end, increment, (TCal curr, int inc) => curr.addYears(inc) as TCal);
}
26 changes: 14 additions & 12 deletions lib/src/gregorian_calendar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,16 @@ const List<int> _sakamotoHelper = const <int>[
/// Represents a single day in the Gregorian Calendar
class GregorianCalendar implements Calendar {
/// Setting any of these to null treats them as 1 or 0 (year)
GregorianCalendar(int year, [int month = 1, int day = 1]) {
GregorianCalendar(this._year, [int? month = 1, int? day = 1]) {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be better to just make these non-null.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, for this constructor despite the comment on line 50 Setting any of these to null treats them as 1 or 0 (year) you should assume these are non-null.

if (year < 0) {
throw new RangeError('Year must be positive');
}
if (day == 0) {
if (day == null || day == 0) {
day = 1;
}
if (month == 0) {
if (month == null || month == 0) {
month = 1;
}
_year = year;
_month = 0;
_day = 0;
_addMonths(month - 1);
Expand All @@ -73,15 +72,18 @@ class GregorianCalendar implements Calendar {

/// Creates a new Date object from the [DateTime] passed in.
GregorianCalendar.fromDateTime(DateTime dt)
: this(dt?.year, dt?.month, dt?.day);
: this(dt.year, dt.month, dt.day);

/// Produces a new Date object from [DateTime] using `now()`
GregorianCalendar.now() : this.fromDateTime(new DateTime.now());

/// Produces a new Date object from [DateTime] using `.now().toUtc()`
GregorianCalendar.utc() : this.fromDateTime(new DateTime.now().toUtc());

int _month, _day, _year;
late int _month;
late int _day;
int _year;

@override
int get month => _month + 1;
@override
Expand Down Expand Up @@ -144,7 +146,7 @@ class GregorianCalendar implements Calendar {
return copy().._addDays(days);
}

void _addDays(int days) {
void _addDays(int? days) {
_day += days ?? 0;

while (_day < 0) {
Expand All @@ -171,7 +173,7 @@ class GregorianCalendar implements Calendar {
return copy().._addMonths(months, clamp: true);
}

void _addMonths(int months, {bool clamp = false}) {
void _addMonths(int? months, {bool clamp = false}) {
final bool wasLastDayInMonth = _day == monthLength - 1;

_month += months ?? 0;
Expand Down Expand Up @@ -220,7 +222,7 @@ class GregorianCalendar implements Calendar {
throw new UnsupportedError(
'Comparing Gregorian and non-Gregorian dates not supported at this time');
}
return toInt().compareTo(other?.toInt());
return toInt().compareTo(other.toInt());
}

/// ISO8061 compatible string version of this date, e.g. 2018-02-03
Expand Down Expand Up @@ -266,7 +268,7 @@ class GregorianCalendar implements Calendar {
/// Will get the nth occurrence of the weekday of month in year
///
/// Returns null if there are not n many weekdays in the month (e.g. the 6th Monday of any month)
static GregorianCalendar getWeekdayOfMonth(
static GregorianCalendar? getWeekdayOfMonth(
int year, int month, int weekday, int nth) {
if (nth < 0) {
throw new RangeError('nth $nth invalid must be positive');
Expand All @@ -293,8 +295,8 @@ class GregorianCalendar implements Calendar {
return dt;
}

static List<GregorianCalendar> getWeekdaysFromWeek(
GregorianCalendar base, WeekdayMask weekdays) {
static List<GregorianCalendar>? getWeekdaysFromWeek(
GregorianCalendar base, WeekdayMask? weekdays) {
if (weekdays == null || weekdays.hasAny == false) {
return null;
}
Expand Down
28 changes: 14 additions & 14 deletions lib/src/weekday_mask.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ class WeekdayMask {
const WeekdayMask(this.mask);

/// Initialize the bitmask from an iterable. If null is passed, will initialize it to 0.
WeekdayMask.fromIterable(Iterable<int> weekdays)
WeekdayMask.fromIterable(Iterable<int>? weekdays)
: mask = weekdays?.fold(
0,
(int prev, int el) => el != null
? prev | WeekdayMask.weekdayToMaskVal[el == 0 ? 7 : el > 7 ? 0 : el]
(int? prev, int? el) => el != null
? prev! | WeekdayMask.weekdayToMaskVal[el == 0 ? 7 : el > 7 ? 0 : el]!
: prev) ??
0;

Expand Down Expand Up @@ -115,7 +115,7 @@ class WeekdayMask {
/// Create a new mask with the 1 based weekday set to the value.
///
/// Passing null for a value will return a copy of this mask.
WeekdayMask setDay(int weekday, bool value) {
WeekdayMask setDay(int? weekday, bool? value) {
if (weekday == null || value == null) {
return new WeekdayMask(mask);
}
Expand All @@ -124,49 +124,49 @@ class WeekdayMask {
}

return new WeekdayMask(
value == true ? mask & weekdayToMaskVal[weekday] : mask & ~weekdayToMaskVal[weekday]);
value == true ? mask & weekdayToMaskVal[weekday]! : mask & ~weekdayToMaskVal[weekday]!);
}

/// See [setDay]. You may pass a custom map of weekday names, where US EN Monday should be 1 and Sunday 7.
WeekdayMask setDayName(String weekdayName, bool value,
WeekdayMask setDayName(String? weekdayName, bool value,
{Map<String, int> dayMap = dayNameToMaskVal}) {
if (weekdayName == null) {
return new WeekdayMask(mask);
}

return new WeekdayMask(value == true
? mask & dayMap[weekdayName.toUpperCase()]
: mask & ~dayMap[weekdayName.toUpperCase()]);
? mask & dayMap[weekdayName.toUpperCase()]!
: mask & ~dayMap[weekdayName.toUpperCase()]!);
}

/// Creates a new mask with the specified weekday's value toggled from true to false or false to true.
WeekdayMask toggleDay(int weekday) {
WeekdayMask toggleDay(int? weekday) {
if (weekday == null) {
return new WeekdayMask(mask);
}
if (weekday == 0) {
weekday = 7;
}

return new WeekdayMask(mask ^ weekdayToMaskVal[weekday]);
return new WeekdayMask(mask ^ weekdayToMaskVal[weekday]!);
}

/// See [toggleDay] and [setDayName]. You may pass a custom map of days if desired.
WeekdayMask toggleDayName(String weekdayName, {Map<String, int> dayMap = dayNameToMaskVal}) {
WeekdayMask toggleDayName(String? weekdayName, {Map<String, int> dayMap = dayNameToMaskVal}) {
if (weekdayName == null) {
return new WeekdayMask(mask);
}

return new WeekdayMask(mask ^ dayMap[weekdayName.toUpperCase()]);
return new WeekdayMask(mask ^ dayMap[weekdayName.toUpperCase()]!);
}

/// Check whether a particular `DateTime.weekday` is set to true in this mask
bool isWeekdaySelected(int weekday) {
return mask & weekdayToMaskVal[weekday] != 0;
return mask & weekdayToMaskVal[weekday]! != 0;
}

bool isDayNameSelected(String day, {Map<String, int> dayMap = dayNameToMaskVal}) {
return mask & dayMap[day.toUpperCase()] != 0;
return mask & dayMap[day.toUpperCase()]! != 0;
}

/// Create an `Iterable<int>` from this mask
Expand Down
4 changes: 2 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
name: date_calendar
version: 0.2.1
description: >
A calendar interface and Gregorian calendar implemenation
A calendar interface and Gregorian calendar implementation
author: Dan Field <dfield@gmail.com>
homepage: https://github.com/dnfield/dart_calendar
dev_dependencies:
test: ^1.3.0
environment:
sdk: '>=2.0.0-dev.8.0 <3.0.0'
sdk: ">=2.12.0 <3.0.0"
2 changes: 1 addition & 1 deletion test/gregorian_calendar_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void main() {
final WeekdayMask weekdaysList =
new WeekdayMask.fromIterable(const <int>[7, 2, 4, 5]);
final List<GregorianCalendar> days = GregorianCalendar.getWeekdaysFromWeek(
new GregorianCalendar(2018, 2, 24), weekdaysList);
new GregorianCalendar(2018, 2, 24), weekdaysList)!;
expect(days.length, equals(weekdaysList.numberOfDaysSelected));
expect(
days,
Expand Down