曜日計算
AlarmClockのソースを参考に今日がXdayだった場合、次にチェックの入ったYdayを求める。という計算ロジックを作成する
AlarmClockのソース
曜日チェックの画面
AlarmClockのAlarms.javaに曜日計算している箇所
/** * returns number of days from today until next alarm * @param c must be set to today */ public int getNextAlarm(Calendar c) { if (mDays == 0) return -1; int today = (c.get(Calendar.DAY_OF_WEEK) + 5) % 7; int day, dayCount; for (dayCount = 0; dayCount < 7; dayCount++) { day = (today + dayCount) % 7; if ((mDays & (1 << day)) > 0) { break; } } return dayCount; }
このソースを見ると、日曜〜土曜までを2^nで定義していると思われる。
mDaysはチェックした日付の論理和が入っている。
で、今日をXdayとして、CalendarクラスからDayOfWeekを求めている。
1bitずつシフトしてYdayの値と論理演算をしてbitが立っている場合はループを抜けている。
このロジックはXdayからYdayまでN日後という場合のNを求めいている
だが、ちょっとまってほしい。
これなんだ?
int today = (c.get(Calendar.DAY_OF_WEEK) + 5) % 7;
これの「+5」の意味が分からない・・
きっとGoogleのことだから、意味のないことはしないはず。
■考察
Calenderクラスでは日曜日を"1"で〜土曜日"6"で定義されている。
これに合わせて、曜日値を2^nにしたら、こうなると思う
日曜日:0x01
月曜日:0x02
火曜日:0x04
水曜日:0x08
木曜日:0x10
金曜日:0x20
土曜日:0x30
ところが、AlarmClockでは以下のように定義されている
* 0x00: no day * 0x01: Monday * 0x02: Tuesday * 0x04: Wednesday * 0x08: Thursday * 0x10: Friday * 0x20: Saturday * 0x40: Sunday
Calenderは日曜日が週初めなのに、AlarmClockでは週初めを月曜にしている・・・
なのでループ値を表にするとこうなる
日曜日 | 月曜日 | 火曜日 | 水曜日 | 木曜日 | 金曜日 | 土曜日 | ||
---|---|---|---|---|---|---|---|---|
google値 | 64 | 1 | 2 | 4 | 8 | 16 | 32 | |
Calendar | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
(today + 5) % 7 | 6 | 0 | 1 | 2 | 3 | 4 | 5 | |
ループカウンタ | bitシフト(値) | |||||||
0 | 6(64) | 0(1) | 1(2) | 2(4) | 3(8) | 4(16) | 5(32) | |
1 | 0(1) | 1(2) | 2(4) | 3(8) | 4(16) | 5(32) | 6(64) | |
2 | 1(2) | 2(4) | 3(8) | 4(16) | 5(32) | 6(64) | 0(1) | |
3 | 2(4) | 3(8) | 4(16) | 5(32) | 6(64) | 0(1) | 2(2) | |
4 | 3(8) | 4(16) | 5(32) | 6(64) | 0(1) | 2(2) | 2(4) | |
5 | 4(16) | 5(32) | 6(64) | 0(1) | 2(2) | 2(4) | 3(8) | |
6 | 5(32) | 6(64) | 0(1) | 2(2) | 2(4) | 3(8) | 4(16) |
- 5をしている理由はわかったが、なんで月曜から始めてんのかがわからない。
個人的にはこうしたい
日曜日:0x01
月曜日:0x02
火曜日:0x04
水曜日:0x08
木曜日:0x10
金曜日:0x20
土曜日:0x30
ソース
public static int getNextAlarm(Calendar c, int mDays) { if (mDays == 0) return -1; int today = c.get(Calendar.DAY_OF_WEEK) - 1; int day, dayCount; for (dayCount = 0; dayCount < 7; dayCount++) { day = (today + dayCount) % 7; if ((mDays & (1 << day)) > 0) { break; } } return dayCount; } }
結果
日曜日 | 月曜日 | 火曜日 | 水曜日 | 木曜日 | 金曜日 | 土曜日 | ||
---|---|---|---|---|---|---|---|---|
値 | 1 | 2 | 4 | 8 | 16 | 32 | 64 | |
Calendar | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
today% 7 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | |
ループカウンタ | bitシフト(値) | |||||||
0 | 0(1) | 1(2) | 2(4) | 3(8) | 4(16) | 5(32) | 6(64) | |
1 | 1(2) | 2(4) | 3(8) | 4(16) | 5(32) | 6(64) | 0(1) | |
2 | 2(4) | 3(8) | 4(16) | 5(32) | 6(64) | 0(1) | 1(2) | |
3 | 3(8) | 4(16) | 5(32) | 6(64) | 0(1) | 1(2) | 2(4) | |
4 | 4(16) | 5(32) | 6(64) | 0(1) | 1(2) | 2(4) | 3(8) | |
5 | 5(32) | 6(64) | 0(1) | 1(2) | 2(4) | 3(8) | 4(16) | |
6 | 6(64) | 0(1) | 1(2) | 2(4) | 3(8) | 4(16) | 5(32) |
■ソース
import java.util.Calendar; public class Main { static final String[] DAY_OF_WEEK = { "dummy", "日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日" }; /** * @param args */ public static void main(String[] args) { int val = 32; int shift = 5; int result = 1 << shift; System.out.println("v:" + val + "res:" + result); // bit表示(土金木水火月日) // days = binary(0101000) 水金をON int days = Integer.parseInt("0101000", 2); System.out.println("days:" + days + " binary:" + Integer.toBinaryString(days)); // 2011/3/24(木) Calendar c = Calendar.getInstance(); c.set(2011, 2, 24); showCalender(c); int add = getNextAlarm(c, days); c.add(Calendar.DAY_OF_YEAR, add); showCalender(c); } public static int getNextAlarm(Calendar c, int mDays) { if (mDays == 0) return -1; int today = c.get(Calendar.DAY_OF_WEEK) - 1; int day, dayCount; // day:bit shiftの数 System.out.println("today:" + today); for (dayCount = 0; dayCount < 7; dayCount++) { day = (today + dayCount) % 7; int value = mDays & (1 << day); System.out.print("[" + DAY_OF_WEEK[day + 1] + "] bit_shift:" + dayCount + " " + " value:" + value); if ((mDays & (1 << day)) > 0) { System.out.println(" !!!HIT"); break; } System.out.println(); } return dayCount; } public static void showCalender(Calendar cal) { StringBuilder sb = new StringBuilder(); sb.append((cal.get(Calendar.MONTH) + 1) + "月 "); sb.append(cal.get(Calendar.DATE) + "日 "); sb.append(cal.get(Calendar.HOUR) + "時 "); sb.append(cal.get(Calendar.MINUTE) + "分 "); sb.append(DAY_OF_WEEK[cal.get(Calendar.DAY_OF_WEEK)]); System.out.println(sb.toString()); } }