Commit e134975c by Sebastián Katzer

Support weekday and weekOfMonth matchers on Android

parent d93534ba
...@@ -151,7 +151,10 @@ public final class Request { ...@@ -151,7 +151,10 @@ public final class Request {
Object every = spec.opt("every"); Object every = spec.opt("every");
if (every instanceof JSONObject) { if (every instanceof JSONObject) {
return new MatchTrigger(getDateMatchingComponents()); List<Integer> cmp1 = getMatchingComponents();
List<Integer> cmp2 = getSpecialMatchingComponents();
return new MatchTrigger(cmp1, cmp2);
} }
Unit unit = getUnit(); Unit unit = getUnit();
...@@ -205,7 +208,7 @@ public final class Request { ...@@ -205,7 +208,7 @@ public final class Request {
* *
* @return [min, hour, day, month, year] * @return [min, hour, day, month, year]
*/ */
private List<Integer> getDateMatchingComponents() { private List<Integer> getMatchingComponents() {
JSONObject every = spec.optJSONObject("every"); JSONObject every = spec.optJSONObject("every");
return Arrays.asList( return Arrays.asList(
...@@ -218,6 +221,22 @@ public final class Request { ...@@ -218,6 +221,22 @@ public final class Request {
} }
/** /**
* Gets an array of all date parts to construct a datetime instance.
*
* @return [min, hour, day, month, year]
*/
private List<Integer> getSpecialMatchingComponents() {
JSONObject every = spec.optJSONObject("every");
return Arrays.asList(
(Integer) every.opt("weekday"),
(Integer) every.opt("weekdayOrdinal"),
(Integer) every.opt("weekOfMonth"),
(Integer) every.opt("quarter")
);
}
/**
* Gets the base date from where to calculate the next trigger date. * Gets the base date from where to calculate the next trigger date.
*/ */
private Date getBaseDate() { private Date getBaseDate() {
......
...@@ -29,7 +29,11 @@ import static de.appplant.cordova.plugin.notification.trigger.DateTrigger.Unit.D ...@@ -29,7 +29,11 @@ import static de.appplant.cordova.plugin.notification.trigger.DateTrigger.Unit.D
import static de.appplant.cordova.plugin.notification.trigger.DateTrigger.Unit.HOUR; import static de.appplant.cordova.plugin.notification.trigger.DateTrigger.Unit.HOUR;
import static de.appplant.cordova.plugin.notification.trigger.DateTrigger.Unit.MINUTE; import static de.appplant.cordova.plugin.notification.trigger.DateTrigger.Unit.MINUTE;
import static de.appplant.cordova.plugin.notification.trigger.DateTrigger.Unit.MONTH; import static de.appplant.cordova.plugin.notification.trigger.DateTrigger.Unit.MONTH;
import static de.appplant.cordova.plugin.notification.trigger.DateTrigger.Unit.WEEK;
import static de.appplant.cordova.plugin.notification.trigger.DateTrigger.Unit.YEAR; import static de.appplant.cordova.plugin.notification.trigger.DateTrigger.Unit.YEAR;
import static java.util.Calendar.DAY_OF_WEEK;
import static java.util.Calendar.WEEK_OF_MONTH;
import static java.util.Calendar.WEEK_OF_YEAR;
/** /**
* Trigger for date matching components. * Trigger for date matching components.
...@@ -39,18 +43,48 @@ public class MatchTrigger extends IntervalTrigger { ...@@ -39,18 +43,48 @@ public class MatchTrigger extends IntervalTrigger {
// Used to determine the interval // Used to determine the interval
private static Unit[] INTERVALS = { null, MINUTE, HOUR, DAY, MONTH, YEAR }; private static Unit[] INTERVALS = { null, MINUTE, HOUR, DAY, MONTH, YEAR };
// Maps these crap where Sunday is the 1st day of the week
private static int[] WEEKDAYS = { 0, 2, 3, 4, 5, 6, 7, 1 };
// Maps these crap where Sunday is the 1st day of the week
private static int[] WEEKDAYS_REV = { 0, 7, 1, 2, 3, 4, 5, 6 };
// The date matching components // The date matching components
private final List<Integer> matchers; private final List<Integer> matchers;
// The special matching components
private final List<Integer> specials;
private static Unit getUnit(List<Integer> matchers, List<Integer> specials) {
Unit unit1 = INTERVALS[1 + matchers.indexOf(null)], unit2 = null;
if (specials.get(0) != null) {
unit2 = WEEK;
}
if (unit2 == null)
return unit1;
return (unit1.compareTo(unit2) < 0) ? unit2 : unit1;
}
/** /**
* Date matching trigger from now. * Date matching trigger from now.
* *
* @param matchers Describes the date matching parts. * @param matchers Describes the date matching parts.
* { day: 15, month: ... } * { day: 15, month: ... }
* @param specials Describes the date matching parts.
* { weekday: 1, weekOfMonth: ... }
*/ */
public MatchTrigger(List<Integer> matchers) { public MatchTrigger(List<Integer> matchers, List<Integer> specials) {
super(1, INTERVALS[1 + matchers.indexOf(null)]); super(1, getUnit(matchers, specials));
if (specials.get(0) != null) {
specials.set(0, WEEKDAYS[specials.get(0)]);
}
this.matchers = matchers; this.matchers = matchers;
this.specials = specials;
} }
/** /**
...@@ -78,7 +112,7 @@ public class MatchTrigger extends IntervalTrigger { ...@@ -78,7 +112,7 @@ public class MatchTrigger extends IntervalTrigger {
} }
if (matchers.get(3) != null) { if (matchers.get(3) != null) {
cal.set(Calendar.MONTH, matchers.get(3)); cal.set(Calendar.MONTH, matchers.get(3) - 1);
} }
if (matchers.get(4) != null) { if (matchers.get(4) != null) {
...@@ -96,80 +130,111 @@ public class MatchTrigger extends IntervalTrigger { ...@@ -96,80 +130,111 @@ public class MatchTrigger extends IntervalTrigger {
* @return null if there's none trigger date. * @return null if there's none trigger date.
*/ */
private Date getTriggerDate (Date base) { private Date getTriggerDate (Date base) {
Calendar date = getBaseTriggerDate(base); Calendar cal = getBaseTriggerDate(base);
Calendar now = getCal(base); Calendar now = getCal(base);
if (date.compareTo(now) >= 0) if (cal.compareTo(now) >= 0)
return date.getTime(); return applySpecials(cal);
if (unit == null || date.get(Calendar.YEAR) < now.get(Calendar.YEAR)) if (unit == null || cal.get(Calendar.YEAR) < now.get(Calendar.YEAR))
return null; return null;
if (date.get(Calendar.MONTH) < now.get(Calendar.MONTH)) { if (cal.get(Calendar.MONTH) < now.get(Calendar.MONTH)) {
switch (unit) { switch (unit) {
case MINUTE: case MINUTE:
case HOUR: case HOUR:
case DAY: case DAY:
case WEEK:
if (matchers.get(4) == null) { if (matchers.get(4) == null) {
return addToDate(date, now, Calendar.YEAR, 1); addToDate(cal, now, Calendar.YEAR, 1);
} else break; break;
} else
return null;
case YEAR: case YEAR:
return addToDate(date, now, Calendar.YEAR, 1); addToDate(cal, now, Calendar.YEAR, 1);
break;
} }
} else } else
if (date.get(Calendar.DAY_OF_YEAR) < now.get(Calendar.DAY_OF_YEAR)) { if (cal.get(Calendar.DAY_OF_YEAR) < now.get(Calendar.DAY_OF_YEAR)) {
switch (unit) { switch (unit) {
case MINUTE: case MINUTE:
case HOUR: case HOUR:
if (matchers.get(3) == null) { if (matchers.get(3) == null) {
return addToDate(date, now, Calendar.MONTH, 1); addToDate(cal, now, Calendar.MONTH, 1);
break;
} else } else
if (matchers.get(4) == null) { if (matchers.get(4) == null) {
return addToDate(date, now, Calendar.YEAR, 1); addToDate(cal, now, Calendar.YEAR, 1);
break;
} }
else break; else
return null;
case MONTH: case MONTH:
return addToDate(date, now, Calendar.MONTH, 1); addToDate(cal, now, Calendar.MONTH, 1);
break;
case YEAR: case YEAR:
return addToDate(date, now, Calendar.YEAR, 1); addToDate(cal, now, Calendar.YEAR, 1);
break;
} }
} else } else
if (date.get(Calendar.HOUR_OF_DAY) < now.get(Calendar.HOUR_OF_DAY)) { if (cal.get(Calendar.HOUR_OF_DAY) < now.get(Calendar.HOUR_OF_DAY)) {
switch (unit) { switch (unit) {
case MINUTE: case MINUTE:
if (matchers.get(2) == null) { if (matchers.get(2) == null) {
return addToDate(date, now, Calendar.DAY_OF_YEAR, 1); addToDate(cal, now, Calendar.DAY_OF_YEAR, 1);
break;
} else } else
if (matchers.get(3) == null) { if (matchers.get(3) == null) {
return addToDate(date, now, Calendar.MONTH, 1); addToDate(cal, now, Calendar.MONTH, 1);
break;
} }
else break; else
return null;
case HOUR: case HOUR:
return addToDate(date, now, Calendar.HOUR_OF_DAY, 0); addToDate(cal, now, Calendar.HOUR_OF_DAY, 0);
break;
case DAY: case DAY:
return addToDate(date, now, Calendar.DAY_OF_YEAR, 1); addToDate(cal, now, Calendar.DAY_OF_YEAR, 1);
break;
case MONTH: case MONTH:
return addToDate(date, now, Calendar.MONTH, 1); addToDate(cal, now, Calendar.MONTH, 1);
break;
case YEAR: case YEAR:
return addToDate(date, now, Calendar.YEAR, 1); addToDate(cal, now, Calendar.YEAR, 1);
break;
} }
} else } else
if (date.get(Calendar.MINUTE) < now.get(Calendar.MINUTE)) { if (cal.get(Calendar.MINUTE) < now.get(Calendar.MINUTE)) {
switch (unit) { switch (unit) {
case MINUTE: case MINUTE:
return addToDate(date, now, Calendar.MINUTE, 1); addToDate(cal, now, Calendar.MINUTE, 1);
break;
case HOUR: case HOUR:
return addToDate(date, now, Calendar.HOUR_OF_DAY, 1); addToDate(cal, now, Calendar.HOUR_OF_DAY, 1);
break;
case DAY: case DAY:
return addToDate(date, now, Calendar.DAY_OF_YEAR, 1); addToDate(cal, now, Calendar.DAY_OF_YEAR, 1);
break;
case MONTH: case MONTH:
return addToDate(date, now, Calendar.MONTH, 1); addToDate(cal, now, Calendar.MONTH, 1);
break;
case YEAR: case YEAR:
return addToDate(date, now, Calendar.YEAR, 1); addToDate(cal, now, Calendar.YEAR, 1);
break;
} }
} }
return null; return applySpecials(cal);
}
private Date applySpecials (Calendar cal) {
if (specials.get(2) != null && !setWeekOfMonth(cal))
return null;
if (specials.get(0) != null && !setDayOfWeek(cal))
return null;
return cal.getTime();
} }
/** /**
...@@ -196,13 +261,93 @@ public class MatchTrigger extends IntervalTrigger { ...@@ -196,13 +261,93 @@ public class MatchTrigger extends IntervalTrigger {
/** /**
* Sets the field value of now to date and adds by count. * Sets the field value of now to date and adds by count.
*/
private void addToDate (Calendar cal, Calendar now, int field, int count) {
cal.set(field, now.get(field));
cal.add(field, count);
}
/**
* Set the day of the year but ensure that the calendar does point to a
* date in future.
* *
* @return The new date. * @param cal The calendar to manipulate.
*
* @return true if the operation could be made.
*/ */
private Date addToDate(Calendar date, Calendar now, int field, int count) { private boolean setDayOfWeek (Calendar cal) {
date.set(field, now.get(field)); cal.setFirstDayOfWeek(Calendar.MONDAY);
date.add(field, count); int day = WEEKDAYS_REV[cal.get(DAY_OF_WEEK)];
return date.getTime(); int month = cal.get(Calendar.MONTH);
int year = cal.get(Calendar.YEAR);
int dayToSet = WEEKDAYS_REV[specials.get(0)];
if (matchers.get(2) != null)
return false;
if (day > dayToSet) {
if (specials.get(2) == null) {
cal.add(WEEK_OF_YEAR, 1);
} else
if (matchers.get(3) == null) {
cal.add(Calendar.MONTH, 1);
} else
if (matchers.get(4) == null) {
cal.add(Calendar.YEAR, 1);
} else
return false;
}
cal.set(DAY_OF_WEEK, specials.get(0));
if (matchers.get(3) != null && cal.get(Calendar.MONTH) != month)
return false;
//noinspection RedundantIfStatement
if (matchers.get(4) != null && cal.get(Calendar.YEAR) != year)
return false;
return true;
} }
/**
* Set the week of the month but ensure that the calendar does point to a
* date in future.
*
* @param cal The calendar to manipulate.
*
* @return true if the operation could be made.
*/
private boolean setWeekOfMonth (Calendar cal) {
int week = cal.get(WEEK_OF_MONTH);
int year = cal.get(Calendar.YEAR);
int weekToSet = specials.get(2);
if (week > weekToSet) {
if (matchers.get(3) == null) {
cal.add(Calendar.MONTH, 1);
} else
if (matchers.get(4) == null) {
cal.add(Calendar.YEAR, 1);
} else
return false;
if (matchers.get(4) != null && cal.get(Calendar.YEAR) != year)
return false;
}
int month = cal.get(Calendar.MONTH);
cal.set(WEEK_OF_MONTH, weekToSet);
if (cal.get(Calendar.MONTH) != month) {
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.MONTH, month);
} else
if (matchers.get(2) == null && week != weekToSet) {
cal.set(DAY_OF_WEEK, 2);
}
return true;
}
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment