/** Compute long due date from DateValue */
 private static long buildNewDueDate(DateTime original, DateValue nextDate) {
   long newDueDate;
   if (nextDate instanceof DateTimeValueImpl) {
     DateTimeValueImpl newDateTime = (DateTimeValueImpl) nextDate;
     DateTime date =
         newDateUtc(
                 newDateTime.year(),
                 newDateTime.month(),
                 newDateTime.day(),
                 newDateTime.hour(),
                 newDateTime.minute(),
                 newDateTime.second())
             .toLocal();
     // time may be inaccurate due to DST, force time to be same
     date =
         date.withHourOfDay(original.getHourOfDay()).withMinuteOfHour(original.getMinuteOfHour());
     newDueDate = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, date.getMillis());
   } else {
     newDueDate =
         Task.createDueDate(
             Task.URGENCY_SPECIFIC_DAY,
             newDate(nextDate.year(), nextDate.month(), nextDate.day()).getMillis());
   }
   return newDueDate;
 }
 /** Compute long due date from DateValue */
 private static long buildNewDueDate(Date original, DateValue nextDate) {
   long newDueDate;
   if (nextDate instanceof DateTimeValueImpl) {
     DateTimeValueImpl newDateTime = (DateTimeValueImpl) nextDate;
     Date date =
         new Date(
             Date.UTC(
                 newDateTime.year() - 1900,
                 newDateTime.month() - 1,
                 newDateTime.day(),
                 newDateTime.hour(),
                 newDateTime.minute(),
                 newDateTime.second()));
     // time may be inaccurate due to DST, force time to be same
     date.setHours(original.getHours());
     date.setMinutes(original.getMinutes());
     newDueDate = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, date.getTime());
   } else {
     newDueDate =
         Task.createDueDate(
             Task.URGENCY_SPECIFIC_DAY,
             new Date(nextDate.year() - 1900, nextDate.month() - 1, nextDate.day()).getTime());
   }
   return newDueDate;
 }
 private void assertDateEquals(String message, long expected, long actual) {
   expected = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, expected);
   actual = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, actual);
   assertEquals(
       message
           + ": Due Date is '"
           + DateUtilities.getDateStringWithWeekday(getContext(), new Date(actual))
           + "', expected '"
           + DateUtilities.getDateStringWithWeekday(getContext(), new Date(expected))
           + "'",
       expected,
       actual);
 }
Exemple #4
0
    /**
     * Read task from json
     *
     * @param json
     * @param model
     * @param metadata
     * @throws JSONException
     */
    public static void taskFromJson(JSONObject json, Task model, ArrayList<Metadata> metadata)
        throws JSONException {
      metadata.clear();
      model.clearValue(Task.REMOTE_ID);
      model.setValue(Task.REMOTE_ID, json.getLong("id"));
      model.setValue(Task.FLAGS, 0);
      readUser(json.getJSONObject("user"), model, Task.USER_ID, Task.USER);
      readUser(json.getJSONObject("creator"), model, Task.CREATOR_ID, null);
      model.setValue(Task.COMMENT_COUNT, json.getInt("comment_count"));
      model.setValue(Task.TITLE, json.getString("title"));
      model.setValue(Task.IMPORTANCE, json.getInt("importance"));
      model.setValue(
          Task.DUE_DATE, model.createDueDate(Task.URGENCY_SPECIFIC_DAY, readDate(json, "due")));
      model.setValue(Task.COMPLETION_DATE, readDate(json, "completed_at"));
      model.setValue(Task.CREATION_DATE, readDate(json, "created_at"));
      model.setValue(Task.DELETION_DATE, readDate(json, "deleted_at"));
      model.setValue(Task.RECURRENCE, json.optString("repeat", ""));
      model.setValue(Task.NOTES, json.optString("notes", ""));
      model.setValue(Task.DETAILS_DATE, 0L);

      JSONArray tags = json.getJSONArray("tags");
      for (int i = 0; i < tags.length(); i++) {
        JSONObject tag = tags.getJSONObject(i);
        String name = tag.getString("name");
        Metadata tagMetadata = new Metadata();
        tagMetadata.setValue(Metadata.KEY, TagService.KEY);
        tagMetadata.setValue(TagService.TAG, name);
        tagMetadata.setValue(TagService.REMOTE_ID, tag.getLong("id"));
        metadata.add(tagMetadata);
      }
    }
  /**
   * Create a task container for the given remote task
   *
   * @throws JSONException
   */
  private GtasksTaskContainer parseRemoteTask(
      com.google.api.services.tasks.model.Task remoteTask, String listId) {
    Task task = new Task();

    ArrayList<Metadata> metadata = new ArrayList<Metadata>();

    task.setValue(Task.TITLE, remoteTask.getTitle());
    task.setValue(Task.CREATION_DATE, DateUtilities.now());
    task.setValue(
        Task.COMPLETION_DATE,
        GtasksApiUtilities.gtasksCompletedTimeToUnixTime(remoteTask.getCompleted(), 0));
    if (remoteTask.getDeleted() == null || !remoteTask.getDeleted().booleanValue())
      task.setValue(Task.DELETION_DATE, 0L);
    else if (remoteTask.getDeleted().booleanValue())
      task.setValue(Task.DELETION_DATE, DateUtilities.now());
    if (remoteTask.getHidden() != null && remoteTask.getHidden().booleanValue())
      task.setValue(Task.DELETION_DATE, DateUtilities.now());

    long dueDate = GtasksApiUtilities.gtasksDueTimeToUnixTime(remoteTask.getDue(), 0);
    long createdDate = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, dueDate);
    task.setValue(Task.DUE_DATE, createdDate);
    task.setValue(Task.NOTES, remoteTask.getNotes());

    Metadata gtasksMetadata = GtasksMetadata.createEmptyMetadata(AbstractModel.NO_ID);
    gtasksMetadata.setValue(GtasksMetadata.ID, remoteTask.getId());
    gtasksMetadata.setValue(GtasksMetadata.LIST_ID, listId);

    GtasksTaskContainer container = new GtasksTaskContainer(task, metadata, gtasksMetadata);
    return container;
  }
Exemple #6
0
  @Override
  public boolean createNew(Task item) {
    if (!item.containsValue(Task.CREATION_DATE))
      item.setValue(Task.CREATION_DATE, DateUtilities.now());
    item.setValue(Task.MODIFICATION_DATE, DateUtilities.now());

    // set up task defaults
    if (!item.containsValue(Task.IMPORTANCE))
      item.setValue(
          Task.IMPORTANCE,
          Preferences.getIntegerFromString(
              R.string.p_default_importance_key, Task.IMPORTANCE_SHOULD_DO));
    if (!item.containsValue(Task.DUE_DATE)) {
      int setting =
          Preferences.getIntegerFromString(R.string.p_default_urgency_key, Task.URGENCY_NONE);
      item.setValue(Task.DUE_DATE, Task.createDueDate(setting, 0));
    }
    createDefaultHideUntil(item);

    setDefaultReminders(item);

    ContentValues values = item.getSetValues();
    boolean result = super.createNew(item);
    if (result) {
      userRetentionMetrics();
      afterSave(item, values);
    }
    return result;
  }
  private static long handleMonthlyRepeat(
      DateTime original, DateValue startDateAsDV, boolean hasDueTime, RRule rrule) {
    if (original.isLastDayOfMonth()) {
      int interval = rrule.getInterval();

      DateTime newDateTime = original.plusMonths(interval);
      long time = newDateTime.withDayOfMonth(newDateTime.getNumberOfDaysInMonth()).getMillis();
      if (hasDueTime) {
        return Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, time);
      } else {
        return Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, time);
      }
    } else {
      return invokeRecurrence(rrule, original, startDateAsDV);
    }
  }
  public void testDailyAndGreaterFreqs() throws ParseException {
    task.setValue(
        Task.DUE_DATE,
        Task.createDueDate(
            Task.URGENCY_SPECIFIC_DAY, DateUtilities.now() - DateUtilities.ONE_WEEK));
    task.setFlag(Task.FLAGS, Task.FLAG_REPEAT_AFTER_COMPLETION, true);

    for (int interval = 1; interval < 7; interval++) {
      for (Frequency freq : Frequency.values()) {
        long next = DateUtilities.now();
        switch (freq) {
          case DAILY:
            next += interval * DateUtilities.ONE_DAY;
            break;
          case WEEKLY:
            next += interval * DateUtilities.ONE_WEEK;
            break;
          case MONTHLY:
            next = DateUtilities.addCalendarMonthsToUnixtime(next, interval);
            break;
          case YEARLY:
            next = DateUtilities.addCalendarMonthsToUnixtime(next, interval * 12);
            break;
          default:
            continue;
        }

        buildRRule(interval, freq);
        nextDueDate = RepeatTaskCompleteListener.computeNextDueDate(task, rrule.toIcal());
        assertDateEquals(freq.toString() + "x" + interval, next, nextDueDate);
        task.setValue(Task.DUE_DATE, nextDueDate);
        assertFalse(task.hasDueTime());
      }
    }
  }
  public void testTimeZoneLate() throws ParseException {
    TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
    task.setValue(Task.DUE_DATE, DateUtilities.now() + DateUtilities.ONE_WEEK);
    task.setFlag(Task.FLAGS, Task.FLAG_REPEAT_AFTER_COMPLETION, true);
    nextDueDate = RepeatTaskCompleteListener.computeNextDueDate(task, rrule.toIcal());

    long expected = Task.createDueDate(Task.URGENCY_TOMORROW, 0);
    assertDateEquals("tomorrow", expected, nextDueDate);
  }
  private static long handleWeeklyRepeatAfterComplete(
      RRule rrule, Date original, boolean hasDueTime) {
    List<WeekdayNum> byDay = rrule.getByDay();
    long newDate = original.getTime();
    newDate += DateUtilities.ONE_WEEK * (rrule.getInterval() - 1);
    Calendar date = Calendar.getInstance();
    date.setTimeInMillis(newDate);

    Collections.sort(byDay, weekdayCompare);
    WeekdayNum next = findNextWeekday(byDay, date);

    do {
      date.add(Calendar.DATE, 1);
    } while (date.get(Calendar.DAY_OF_WEEK) != next.wday.javaDayNum);

    long time = date.getTimeInMillis();
    if (hasDueTime) return Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, time);
    else return Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, time);
  }
 private void mergeDates(Task remote, Task local) {
   if (remote.hasDueDate() && local.hasDueTime()) {
     Date newDate = new Date(remote.getValue(Task.DUE_DATE));
     Date oldDate = new Date(local.getValue(Task.DUE_DATE));
     newDate.setHours(oldDate.getHours());
     newDate.setMinutes(oldDate.getMinutes());
     newDate.setSeconds(oldDate.getSeconds());
     long setDate = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, newDate.getTime());
     remote.setValue(Task.DUE_DATE, setDate);
   }
 }
  private long getDate(long start, int which, int dayOfWeek) {
    Calendar c = Calendar.getInstance();
    c.setTimeInMillis(start);
    int direction = which > 0 ? 1 : -1;

    while (c.get(Calendar.DAY_OF_WEEK) != dayOfWeek) {
      c.add(Calendar.DAY_OF_MONTH, direction);
    }
    c.add(Calendar.DAY_OF_MONTH, (Math.abs(which) - 1) * direction * 7);
    return Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, c.getTimeInMillis());
  }
  private static long handleWeeklyRepeatAfterComplete(
      RRule rrule, DateTime original, boolean hasDueTime) {
    List<WeekdayNum> byDay = rrule.getByDay();
    long newDate = original.getMillis();
    newDate += DateUtilities.ONE_WEEK * (rrule.getInterval() - 1);
    DateTime date = new DateTime(newDate);

    Collections.sort(byDay, weekdayCompare);
    WeekdayNum next = findNextWeekday(byDay, date);

    do {
      date = date.plusDays(1);
    } while (date.getDayOfWeek() != next.wday.javaDayNum);

    long time = date.getMillis();
    if (hasDueTime) {
      return Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, time);
    } else {
      return Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, time);
    }
  }
  @Test
  public void testDueDateSpecificTime() throws ParseException {
    buildRRule(1, Frequency.DAILY);

    // test specific day & time
    long dayWithTime =
        Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, newDate(2010, 8, 1, 10, 4, 0).getTime());
    task.setValue(Task.DUE_DATE, dayWithTime);

    long nextDayWithTime = dayWithTime + DateUtilities.ONE_DAY;
    nextDueDate = RepeatTaskCompleteListener.computeNextDueDate(task, rrule.toIcal(), false);
    assertDateTimeEquals(nextDayWithTime, nextDueDate);
  }
  /** test multiple days per week, multiple intervals - COMPLETE DATE */
  @Test
  public void testCompleteDateMultiWeek() throws Exception {
    for (Weekday wday : Weekday.values()) {
      buildRRule(2, Frequency.WEEKLY, wday);
      computeNextDueDate(true);
      long expected = getDate(DateUtilities.now() + DateUtilities.ONE_DAY, NEXT, wday.javaDayNum);
      nextDueDate = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, nextDueDate);
      assertEquals(expected, nextDueDate);
    }

    for (Weekday wday1 : Weekday.values()) {
      for (Weekday wday2 : Weekday.values()) {
        if (wday1 == wday2) continue;

        buildRRule(2, Frequency.WEEKLY, wday1, wday2);
        long nextOne = getDate(DateUtilities.now() + DateUtilities.ONE_DAY, NEXT, wday1.javaDayNum);
        long nextTwo = getDate(DateUtilities.now() + DateUtilities.ONE_DAY, NEXT, wday2.javaDayNum);
        computeNextDueDate(true);
        nextDueDate = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, nextDueDate);
        assertEquals(Math.min(nextOne, nextTwo), nextDueDate);
      }
    }
  }
 static long handleSubdayRepeat(DateTime startDate, RRule rrule) {
   long millis;
   switch (rrule.getFreq()) {
     case HOURLY:
       millis = DateUtilities.ONE_HOUR;
       break;
     case MINUTELY:
       millis = DateUtilities.ONE_MINUTE;
       break;
     default:
       throw new RuntimeException(
           "Error handing subday repeat: " + rrule.getFreq()); // $NON-NLS-1$
   }
   long newDueDate = startDate.getMillis() + millis * rrule.getInterval();
   return Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, newDueDate);
 }
  @Test
  public void testCompletionDateSpecificTime() throws ParseException {
    buildRRule(1, Frequency.DAILY);

    // test specific day & time
    long dayWithTime =
        Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, newDate(2010, 8, 1, 10, 4, 0).getTime());
    task.setValue(Task.DUE_DATE, dayWithTime);

    Date todayWithTime = newDate();
    todayWithTime.setHours(10);
    todayWithTime.setMinutes(4);
    todayWithTime.setSeconds(1);
    long nextDayWithTimeLong = todayWithTime.getTime();
    nextDayWithTimeLong += DateUtilities.ONE_DAY;
    nextDayWithTimeLong = nextDayWithTimeLong / 1000L * 1000;

    nextDueDate = RepeatTaskCompleteListener.computeNextDueDate(task, rrule.toIcal(), true);
    assertDateTimeEquals(nextDayWithTimeLong, nextDueDate);
  }
Exemple #18
0
  // ---------------------DATE--------------------------
  // Handles setting the task's date.
  // Day of week (e.g. Monday, Tuesday,..) is overridden by a set date (e.g. October 23 2013).
  // Vague times (e.g. breakfast, night) are overridden by a set time (9 am, at 10, 17:00)
  private static boolean dayHelper(Task task) {
    if (task.containsNonNullValue(Task.DUE_DATE)) {
      return false;
    }
    String inputText = task.getValue(Task.TITLE);
    Calendar cal = null;
    Boolean containsSpecificTime = false;
    String[] daysOfWeek = {
      "(?i)(\\(|\\b)today(\\)|\\b)",
      "(?i)(\\(|\\b)tomorrow(\\)|\\b)",
      "(?i)(\\(|\\b)mon(day(\\)|\\b)|(\\)|\\.))",
      "(?i)(\\(|\\b)tue(sday(\\)|\\b)|(\\)|\\.))",
      "(?i)(\\(|\\b)wed(nesday(\\)|\\b)|(\\)|\\.))",
      "(?i)(\\(|\\b)thu(rsday(\\)|\\b)|(\\)|\\.))",
      "(?i)(\\(|\\b)fri(day(\\)|\\b)|(\\)|\\.))",
      "(?i)(\\(|\\b)sat(urday(\\)|\\b)|(\\)|\\.))",
      "(?i)(\\(|\\b)sun(day(\\)|\\b)|(\\)|\\.))"
    };

    for (String date : daysOfWeek) {
      Pattern pattern = Pattern.compile(date);
      Matcher m = pattern.matcher(inputText);
      if (m.find()) {
        String toParse = stripParens(m.group(0));
        Calendar dayCal = AstridChronic.parse(toParse).getBeginCalendar();
        cal = dayCal;
        inputText = removeIfParenthetical(m, inputText);
        // then put it into task
      }
    }

    String[] dates = {
      "(?i)(\\(|\\b)(jan(\\.|uary))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?(\\)|\\b)",
      "(?i)(\\(|\\b)(feb(\\.|ruary))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?(\\)|\\b)",
      "(?i)(\\(|\\b)(mar(\\.|ch))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?(\\)|\\b)",
      "(?i)(\\(|\\b)(apr(\\.|il))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?(\\)|\\b)",
      "(?i)(\\(|\\b)(may())(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?(\\)|\\b)",
      "(?i)(\\(|\\b)(jun(\\.|e))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?(\\)|\\b)",
      "(?i)(\\(|\\b)(jul(\\.|y))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?(\\)|\\b)",
      "(?i)(\\(|\\b)(aug(\\.|ust))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?(\\)|\\b)",
      "(?i)(\\(|\\b)(sep(\\.|tember))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?(\\)|\\b)",
      "(?i)(\\(|\\b)(oct(\\.|ober))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?(\\)|\\b)",
      "(?i)(\\(|\\b)(nov(\\.|ember))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?(\\)|\\b)",
      "(?i)(\\(|\\b)(dec(\\.|ember))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?(\\)|\\b)"
    };

    // m.group(2) = "month"
    // m.group(5) = "day"
    for (String date : dates) {
      Pattern pattern = Pattern.compile(date);
      Matcher m = pattern.matcher(inputText);

      if (m.find()) {
        Calendar dateCal = Chronic.parse(m.group(2)).getBeginCalendar();
        if (m.group(5) != null) {
          dateCal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(m.group(5)));
        }
        Calendar today = Calendar.getInstance();
        if (m.group(6) != null) {
          dateCal.set(Calendar.YEAR, Integer.parseInt(m.group(6).trim()));
        } else if (today.get(Calendar.MONTH) - dateCal.get(Calendar.MONTH)
            > 1) { // if more than a month in the past
          dateCal.set(Calendar.YEAR, dateCal.get(Calendar.YEAR) + 1);
        }
        if (cal == null) {
          cal = dateCal;
        } else {
          cal.set(Calendar.DAY_OF_MONTH, dateCal.get(Calendar.DAY_OF_MONTH));
          cal.set(Calendar.MONTH, dateCal.get(Calendar.MONTH));
          cal.set(Calendar.YEAR, dateCal.get(Calendar.YEAR));
        }
        inputText = removeIfParenthetical(m, inputText);
      }
    }

    // for dates in the format MM/DD
    Pattern p =
        Pattern.compile(
            "(?i)(\\(|\\b)(1[0-2]|0?[1-9])(\\/|-)(3[0-1]|[0-2]?[0-9])(\\/|-)?(\\d{4}|\\d{2})?(\\)|\\b)");
    Matcher match = p.matcher(inputText);
    if (match.find()) {
      Calendar dCal = Calendar.getInstance();
      setCalendarToDefaultTime(dCal);
      dCal.set(Calendar.MONTH, Integer.parseInt(match.group(2).trim()) - 1);
      dCal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(match.group(4)));
      if (match.group(6) != null && !(match.group(6).trim()).equals("")) {
        String yearString = match.group(6);
        if (match.group(6).length() == 2) {
          yearString = "20" + match.group(6);
        }
        dCal.set(Calendar.YEAR, Integer.parseInt(yearString));
      }

      if (cal == null) {
        cal = dCal;
      } else {
        cal.set(Calendar.DAY_OF_MONTH, dCal.get(Calendar.DAY_OF_MONTH));
        cal.set(Calendar.MONTH, dCal.get(Calendar.MONTH));
        cal.set(Calendar.YEAR, dCal.get(Calendar.YEAR));
      }
      inputText = removeIfParenthetical(match, inputText);
    }

    HashMap<String, Integer> dayTimes = new HashMap<String, Integer>();
    dayTimes.put("(?i)\\bbreakfast\\b", 8);
    dayTimes.put("(?i)\\blunch\\b", 12);
    dayTimes.put("(?i)\\bsupper\\b", 18);
    dayTimes.put("(?i)\\bdinner\\b", 18);
    dayTimes.put("(?i)\\bbrunch\\b", 10);
    dayTimes.put("(?i)\\bmorning\\b", 8);
    dayTimes.put("(?i)\\bafternoon\\b", 15);
    dayTimes.put("(?i)\\bevening\\b", 19);
    dayTimes.put("(?i)\\bnight\\b", 19);
    dayTimes.put("(?i)\\bmidnight\\b", 0);
    dayTimes.put("(?i)\\bnoon\\b", 12);

    Set<String> keys = dayTimes.keySet();
    for (String dayTime : keys) {
      Pattern pattern = Pattern.compile(dayTime);
      Matcher m = pattern.matcher(inputText);
      if (m.find()) {
        containsSpecificTime = true;
        int timeHour = dayTimes.get(dayTime);
        Calendar dayTimesCal = Calendar.getInstance();
        setCalendarToDefaultTime(dayTimesCal);
        dayTimesCal.set(Calendar.HOUR, timeHour);
        if (cal == null) {
          cal = dayTimesCal;
        } else {
          setCalendarToDefaultTime(cal);
          cal.set(Calendar.HOUR, timeHour);
        }
      }
    }

    String[] times = {
      // [time] am/pm
      "(?i)(\\b)([01]?\\d):?([0-5]\\d)? ?([ap]\\.?m?\\.?)\\b",
      // army time
      "(?i)\\b(([0-2]?[0-9]):([0-5][0-9]))(\\b)",
      // [int] o'clock
      "(?i)\\b(([01]?\\d)() ?o'? ?clock) ?([ap]\\.?m\\.?)?\\b",
      // at [int]
      "(?i)(\\bat) ([01]?\\d)()($|\\D($|\\D))"

      // m.group(2) holds the hour
      // m.group(3) holds the minutes
      // m.group(4) holds am/pm
    };

    for (String time : times) {
      Pattern pattern = Pattern.compile(time);
      Matcher m = pattern.matcher(inputText);
      if (m.find()) {
        containsSpecificTime = true;
        Calendar today = Calendar.getInstance();
        Calendar timeCal = Calendar.getInstance();
        setCalendarToDefaultTime(timeCal);
        timeCal.set(Calendar.HOUR, Integer.parseInt(m.group(2)));

        if (m.group(3) != null && !m.group(3).trim().equals("")) {
          timeCal.set(Calendar.MINUTE, Integer.parseInt(m.group(3)));
        } else {
          timeCal.set(Calendar.MINUTE, 0);
        }
        if (Integer.parseInt(m.group(2)) <= 12) {
          timeCal.set(Calendar.AM_PM, ampmToNumber(m.group(4)));
        }

        // sets it to the next occurrence of that hour if no am/pm is provided. doesn't include
        // military time
        if (Integer.parseInt(m.group(2)) <= 12
            && (m.group(4) == null || (m.group(4).trim()).equals(""))) {
          while (timeCal.getTime().getTime() < today.getTime().getTime()) {
            timeCal.set(Calendar.HOUR_OF_DAY, timeCal.get(Calendar.HOUR_OF_DAY) + 12);
          }
        } else { // if am/pm is provided and the time is in the past, set it to the next day.
                 // Military time included.
          if (timeCal.get(Calendar.HOUR) != 0
              && (timeCal.getTime().getTime() < today.getTime().getTime())) {
            timeCal.set(Calendar.DAY_OF_MONTH, timeCal.get(Calendar.DAY_OF_MONTH) + 1);
          }
          if (timeCal.get(Calendar.HOUR) == 0) {
            timeCal.set(Calendar.HOUR, 12);
          }
        }

        if (cal == null) {
          cal = timeCal;
        } else {
          cal.set(Calendar.HOUR, timeCal.get(Calendar.HOUR));
          cal.set(Calendar.MINUTE, timeCal.get(Calendar.MINUTE));
          cal.set(Calendar.SECOND, timeCal.get(Calendar.SECOND));
          cal.set(Calendar.AM_PM, timeCal.get(Calendar.AM_PM));
        }
        break;
      }
    }

    if (cal
        != null) { // if at least one of the above has been called, write to task. else do nothing.
      if (!TextUtils.isEmpty(inputText)) {
        task.setValue(Task.TITLE, inputText);
      }
      if (containsSpecificTime) {
        task.setValue(
            Task.DUE_DATE,
            Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, cal.getTime().getTime()));
      } else {
        task.setValue(
            Task.DUE_DATE, Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, cal.getTime().getTime()));
      }
      return true;
    }
    return false;
  }