📄 alarmentry.java
字号:
}
/**
* daysInMonth can't use simple offsets like the other fields, because the
* number of days varies per month (think of an alarm that executes on every
* 31st). Instead we advance month and dayInMonth together until we're on a
* matching value pair.
*/
void updateDayOfMonthAndMonth( Calendar alarm )
{
int currentMonth = alarm.get( Calendar.MONTH );
int currentDayOfMonth = alarm.get( Calendar.DAY_OF_MONTH );
int offset = 0;
// loop until we have a valid day AND month (if current is invalid)
while( !isIn(currentMonth, months) || !isIn(currentDayOfMonth, daysOfMonth) )
{
// if current month is invalid, advance to 1st day of next valid month
if( !isIn(currentMonth, months) )
{
offset = getOffsetToNextOrEqual( currentMonth, minMonth, maxMonth, months );
alarm.add( Calendar.MONTH, offset );
alarm.set( Calendar.DAY_OF_MONTH, 1 );
currentDayOfMonth = 1;
}
// advance to the next valid day of month, if necessary
if( !isIn(currentDayOfMonth, daysOfMonth) )
{
int maxDayOfMonth = alarm.getActualMaximum( Calendar.DAY_OF_MONTH );
offset = getOffsetToNextOrEqual( currentDayOfMonth, minDayOfMonth, maxDayOfMonth, daysOfMonth );
alarm.add( Calendar.DAY_OF_MONTH, offset );
}
currentMonth = alarm.get( Calendar.MONTH );
currentDayOfMonth = alarm.get( Calendar.DAY_OF_MONTH );
}
}
void updateDayOfWeekAndMonth( Calendar alarm )
{
int currentMonth = alarm.get( Calendar.MONTH );
int currentDayOfWeek = alarm.get( Calendar.DAY_OF_WEEK );
int offset = 0;
// loop until we have a valid day AND month (if current is invalid)
while( !isIn(currentMonth, months) || !isIn(currentDayOfWeek, daysOfWeek) )
{
// if current month is invalid, advance to 1st day of next valid month
if( !isIn(currentMonth, months) )
{
offset = getOffsetToNextOrEqual( currentMonth, minMonth, maxMonth, months );
alarm.add( Calendar.MONTH, offset );
alarm.set( Calendar.DAY_OF_MONTH, 1 );
currentDayOfWeek = alarm.get( Calendar.DAY_OF_WEEK );
}
// advance to the next valid day of week, if necessary
if( !isIn(currentDayOfWeek, daysOfWeek) )
{
offset = getOffsetToNextOrEqual( currentDayOfWeek, minDayOfWeek, maxDayOfWeek, daysOfWeek );
alarm.add( Calendar.DAY_OF_YEAR, offset );
}
currentDayOfWeek = alarm.get( Calendar.DAY_OF_WEEK );
currentMonth = alarm.get( Calendar.MONTH );
}
}
// ----------------------------------------------------------------------
// General utility methods
// ----------------------------------------------------------------------
/**
* if values = {-1}
* offset is 1 (because next value definitely matches)
* if current < last(values)
* offset is diff to next valid value
* if current >= last(values)
* offset is diff to values[0], wrapping from max to min
*/
static int getOffsetToNext( int current, int min, int max, int[] values )
{
int offset = 0;
// find the distance to the closest valid value > current (wrapping if neccessary)
// {-1} means * -- offset is 1 because current++ is valid value
if (values[0] == -1 )
{
offset = 1;
}
else
{
// need to wrap
if( current >= last(values) )
{
int next = values[0];
offset = (max-current+1) + (next-min);
}
else // current < max(values) -- find next valid value after current
{
findvalue:
for( int i=0; i<values.length; i++ )
{
if( current < values[i] )
{
offset = values[i] - current;
break findvalue;
}
}
} // end current < max(values)
}
return offset;
}
/**
* if values = {-1} or current is valid
* offset is 0.
* if current < last(values)
* offset is diff to next valid value
* if current >= last(values)
* offset is diff to values[0], wrapping from max to min
*/
static int getOffsetToNextOrEqual( int current, int min, int max, int[] values )
{
int offset = 0;
int[] safeValues = null;
// find the distance to the closest valid value >= current (wrapping if necessary)
// {-1} means * -- offset is 0 if current is valid value
if (values[0] == -1 || isIn(current, values) )
{
offset = 0;
}
else
{
safeValues = discardValuesOverMax( values, max );
// need to wrap
if( current > last(safeValues) )
{
int next = safeValues[0];
offset = (max-current+1) + (next-min);
}
else // current <= max(values) -- find next valid value
{
findvalue:
for( int i=0; i<values.length; i++ )
{
if( current < safeValues[i] )
{
offset = safeValues[i] - current;
break findvalue;
}
}
} // end current <= max(values)
}
return offset;
}
/**
* handles -1 in values as * and returns true
* otherwise returns true iff given value is in the array
*/
static boolean isIn( int find, int[] values )
{
if( values[0] == -1 )
{
return true;
}
else
{
for( int i=0; i<values.length; i++ )
{
if( find == values[i] )
return true;
}
return false;
}
}
/**
* @return the last int in the array
*/
static int last( int[] intArray )
{
return intArray[ intArray.length - 1 ];
}
/**
* Assumes inputted values are not null, have at least one value, and are in
* ascending order.
* @return copy of values without any trailing values that exceed the max
*/
static int[] discardValuesOverMax( int[] values, int max )
{
int[] safeValues = null;
for( int i=0; i<values.length; i++ )
{
if( values[i] > max )
{
safeValues = new int[i];
System.arraycopy( values, 0, safeValues, 0, i );
return safeValues;
}
}
return values;
}
private static String arrToString( int[] intArray )
{
if( intArray == null )
return "null";
if( intArray.length == 0 )
return "{}";
String s = "{";
for( int i=0; i<intArray.length-1; i++ )
{
s += intArray[i] + ", ";
}
s += intArray[intArray.length-1] + "}";
return s;
}
// ----------------------------------------------------------------------
// Comparable interface
// ----------------------------------------------------------------------
/**
* Compares this AlarmEntry with the specified AlarmEntry for order.
* One twist -- if the alarmTime matches, this alarm will STILL place
* itself before the other based on the lastUpdateTime. If the other
* alarm has been rung more recently, this one should get priority.
*
* @param obj the AlarmEntry with which to compare.
* @return a negative integer, zero, or a positive integer as this
* AlarmEntry is less than, equal to, or greater than the given
* AlarmEntry.
* @exception ClassCastException if the specified Object's type
* prevents it from being compared to this AlarmEntry.
*/
public int compareTo(Object obj) {
AlarmEntry other = (AlarmEntry)obj;
if (alarmTime < other.alarmTime)
return -1;
else if (alarmTime > other.alarmTime)
return 1;
else // alarmTime == other.alarmTime
{
if( lastUpdateTime < other.lastUpdateTime )
return -1;
else if( lastUpdateTime > other.lastUpdateTime)
return 1;
else
return 0;
}
}
/**
* Indicates whether some other AlarmEntry is "equal to" this one.
* This is where the name is important, since two alarms can have the
* exact same schedule.
*
* @param obj the AlarmEntry with which to compare.
* @return <code>true if this AlarmEntry has the same name,
* <code>alarmTime</code> AND the same schedule as the
* obj argument;
* <code>false</code> otherwise.
*/
public boolean equals(Object obj) {
AlarmEntry entry = null;
if( obj == null || !(obj instanceof AlarmEntry) )
return false;
entry = (AlarmEntry)obj;
return ( name.equals(entry.name)
&& alarmTime == entry.alarmTime
&& isRelative == entry.isRelative
&& isRepeating == entry.isRepeating
&& Arrays.equals(minutes, entry.minutes)
&& Arrays.equals(hours, entry.hours)
&& Arrays.equals(daysOfMonth, entry.daysOfMonth)
&& Arrays.equals(months, entry.months)
&& Arrays.equals(daysOfWeek, entry.daysOfWeek) );
}
/**
* @return a string representation of this alarm.
*/
public String toString() {
if (year != -1) {
return "Alarm ("+name+") at " + new Date(alarmTime);
}
StringBuffer sb = new StringBuffer("Alarm ("+name+") params");
sb.append(" minute="); sb.append( arrToString(minutes) );
sb.append(" hour="); sb.append( arrToString(hours) );
sb.append(" dayOfMonth="); sb.append( arrToString(daysOfMonth) );
sb.append(" month="); sb.append( arrToString(months) );
sb.append(" dayOfWeek="); sb.append( arrToString(daysOfWeek) );
sb.append(" (next alarm date=" + new Date(alarmTime) + ")");
return sb.toString();
}
/**
* some unit testing...
*/
public static void main( String[] args ) {
System.out.println( "GETTING OFFSETS" );
System.out.println( "getOffsetToNext(3, 0, 11, new int[]{3,5,7,9}) = " +
getOffsetToNext(3, 0, 11, new int[]{3,5,7,9}) );
System.out.println( "getOffsetToNextOrEqual(3, 0, 11, new int[]{3,5,7,9}) = " +
getOffsetToNextOrEqual(3, 0, 11, new int[]{3,5,7,9}) );
System.out.println();
System.out.println( "getOffsetToNext(9, 0, 11, new int[]{3,5,7,9}) = " +
getOffsetToNext(9, 0, 11, new int[]{3,5,7,9}) );
System.out.println( "getOffsetToNextOrEqual(9, 0, 11, new int[]{3,5,7,9}) = " +
getOffsetToNextOrEqual(9, 0, 11, new int[]{3,5,7,9}) );
System.out.println();
System.out.println( "getOffsetToNext(0, 0, 11, new int[]{0}) = " +
getOffsetToNext(0, 0, 11, new int[]{0}) );
System.out.println( "getOffsetToNextOrEqual(0, 0, 11, new int[]{0}) = " +
getOffsetToNextOrEqual(0, 0, 11, new int[]{0}) );
System.out.println();
System.out.println( "getOffsetToNext(5, 0, 11, new int[]{5}) = " +
getOffsetToNext(5, 0, 11, new int[]{5}) );
System.out.println( "getOffsetToNextOrEqual(5, 0, 11, new int[]{5}) = " +
getOffsetToNextOrEqual(5, 0, 11, new int[]{5}) );
System.out.println();
System.out.println( "getOffsetToNext(0, 0, 11, new int[]{-1}) = " +
getOffsetToNext(0, 0, 11, new int[]{-1}) );
System.out.println( "getOffsetToNextOrEqual(0, 0, 11, new int[]{-1}) = " +
getOffsetToNextOrEqual(0, 0, 11, new int[]{-1}) );
System.out.println();
System.out.println();
System.out.println( "discardValuesOverMax(new int[]{0,1,2,3,4,5,6}, 4)) = " +
arrToString(discardValuesOverMax(new int[]{0,1,2,3,4,5,6}, 4)) );
System.out.println( "discardValuesOverMax(new int[]{0,1,2,3,4,5,6}, 6)) = " +
arrToString(discardValuesOverMax(new int[]{0,1,2,3,4,5,6}, 6)) );
System.out.println( "discardValuesOverMax(new int[]{0,1,2,3,4,5,6}, 0)) = " +
arrToString(discardValuesOverMax(new int[]{0,1,2,3,4,5,6}, 0)) );
System.out.println( "discardValuesOverMax(new int[]{0,1,2,3,4,5,6}, 7)) = " +
arrToString(discardValuesOverMax(new int[]{0,1,2,3,4,5,6}, 7)) );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -