package org.frasermccrossan.ltc; import java.util.Calendar; import java.util.regex.Matcher; import java.util.regex.Pattern; /* a very simple time representation class since we don't really want the sophistication * of Calendar; really just acts as a return value of a regexp-parsed time */ public class HourMinute { public static final int AM = 0; public static final int PM = 2; public static final int NO_AMPM = -1; static final int DAY_MINUTES = 24 * 60; static final int HALF_DAY_MINUTES = DAY_MINUTES / 2; public int minsAfterMidnight; // absolute number of minutes after midnight /* this needs to match the following forms and extract the hour, minutes and am/pmage: * "12:04" * "12:04 [AP]" * :12:04:08 [AP]" */ static final Pattern TIME_PATTERN = Pattern.compile("(\\d{1,2}):(\\d{2})(:\\d{2})? ?([AP])?"); public int hour = -1; public int minute; public int am_pm = NO_AMPM; HourMinute(Calendar reference, String textTime) { Matcher m = TIME_PATTERN.matcher(textTime); if (m.find()) { hour=Integer.valueOf(m.group(1)); if (hour == 12) { hour = 0; } // makes calculations easier minute = Integer.valueOf(m.group(2)); String am_pm_s = m.group(4); if (am_pm_s != null) { am_pm_s = am_pm_s.toLowerCase(); if (am_pm_s.equals("p")) { am_pm = PM; hour += 12; // we fixed the hour values above, so 12 is zero } else { am_pm = AM; } } minsAfterMidnight = hour * 60 + minute; if (!hasAmPm()) { /* no am/pm indicator, assume it's within 12 hours of now and take a best guess, * then correct the hour value */ int ref12Hour = reference.get(Calendar.HOUR); // 12-hour hour of reference int refMinute = reference.get(Calendar.MINUTE); // minute of reference if (ref12Hour == 12) { ref12Hour = 0; } // easier calculation int refMinutes12 = ref12Hour * 60 + refMinute; int ref24hour = reference.get(Calendar.HOUR_OF_DAY); int refMinutes24 = ref24hour * 60 + refMinute; if (minsAfterMidnight >= refMinutes12) { /* the 12-hour time hour is greater than the reference 12-hour, assume it's * *after* the reference time in the same 12-hour segment */ minsAfterMidnight = refMinutes24 + (minsAfterMidnight - refMinutes12); } else { /* otherwise, the 12-hour time is less than the reference, so it's * in the "other" 12 hour segment */ if (refMinutes24 >= HALF_DAY_MINUTES) { // reference is second half of day, so time we seek is after midnight, in the early hours // we need do nothing } else { // reference is first half of day, so time we seek is afternoon minsAfterMidnight += HALF_DAY_MINUTES; } } hour = minsAfterMidnight / 60; minute = minsAfterMidnight % 60; } //Log.d("HourMinute", String.format("orig %s hour %d min %d", textTime, hour, minute)); } } public boolean isValid() { return hour >= 0; } public Boolean hasAmPm() { return am_pm != NO_AMPM; } int timeDiff(Calendar reference) { if (isValid()) { /* the minsAfterMidnight value here should now be correct whether we had * an AM/PM time or not, so the calculation is simple */ int refMinsAfterMidnight = reference.get(Calendar.HOUR_OF_DAY) * 60 + reference.get(Calendar.MINUTE); int diff = minsAfterMidnight - refMinsAfterMidnight; if (diff >= 0) { return diff; } else { return DAY_MINUTES + diff; } } else { return Prediction.VERY_FAR_AWAY; } } }