1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.calendar; 18 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.text.format.DateUtils; 22 import android.text.format.Time; 23 import android.util.TimeFormatException; 24 25 import com.android.calendarcommon2.EventRecurrence; 26 27 import java.util.Calendar; 28 29 public class EventRecurrenceFormatter 30 { 31 32 private static int[] mMonthRepeatByDayOfWeekIds; 33 private static String[][] mMonthRepeatByDayOfWeekStrs; 34 getRepeatString(Context context, Resources r, EventRecurrence recurrence, boolean includeEndString)35 public static String getRepeatString(Context context, Resources r, EventRecurrence recurrence, 36 boolean includeEndString) { 37 String endString = ""; 38 if (includeEndString) { 39 StringBuilder sb = new StringBuilder(); 40 if (recurrence.until != null) { 41 try { 42 Time t = new Time(); 43 t.parse(recurrence.until); 44 final String dateStr = DateUtils.formatDateTime(context, 45 t.toMillis(false), DateUtils.FORMAT_NUMERIC_DATE); 46 sb.append(r.getString(R.string.endByDate, dateStr)); 47 } catch (TimeFormatException e) { 48 } 49 } 50 51 if (recurrence.count > 0) { 52 sb.append(r.getQuantityString(R.plurals.endByCount, recurrence.count, 53 recurrence.count)); 54 } 55 endString = sb.toString(); 56 } 57 58 // TODO Implement "Until" portion of string, as well as custom settings 59 int interval = recurrence.interval <= 1 ? 1 : recurrence.interval; 60 switch (recurrence.freq) { 61 case EventRecurrence.DAILY: 62 return r.getQuantityString(R.plurals.daily, interval, interval) + endString; 63 case EventRecurrence.WEEKLY: { 64 if (recurrence.repeatsOnEveryWeekDay()) { 65 return r.getString(R.string.every_weekday) + endString; 66 } else { 67 String string; 68 69 int dayOfWeekLength = DateUtils.LENGTH_MEDIUM; 70 if (recurrence.bydayCount == 1) { 71 dayOfWeekLength = DateUtils.LENGTH_LONG; 72 } 73 74 StringBuilder days = new StringBuilder(); 75 76 // Do one less iteration in the loop so the last element is added out of the 77 // loop. This is done so the comma is not placed after the last item. 78 79 if (recurrence.bydayCount > 0) { 80 int count = recurrence.bydayCount - 1; 81 for (int i = 0 ; i < count ; i++) { 82 days.append(dayToString(recurrence.byday[i], dayOfWeekLength)); 83 days.append(", "); 84 } 85 days.append(dayToString(recurrence.byday[count], dayOfWeekLength)); 86 87 string = days.toString(); 88 } else { 89 // There is no "BYDAY" specifier, so use the day of the 90 // first event. For this to work, the setStartDate() 91 // method must have been used by the caller to set the 92 // date of the first event in the recurrence. 93 if (recurrence.startDate == null) { 94 return null; 95 } 96 97 int day = EventRecurrence.timeDay2Day(recurrence.startDate.weekDay); 98 string = dayToString(day, DateUtils.LENGTH_LONG); 99 } 100 return r.getQuantityString(R.plurals.weekly, interval, interval, string) 101 + endString; 102 } 103 } 104 case EventRecurrence.MONTHLY: { 105 if (recurrence.bydayCount == 1) { 106 int weekday = recurrence.startDate.weekDay; 107 // Cache this stuff so we won't have to redo work again later. 108 cacheMonthRepeatStrings(r, weekday); 109 int dayNumber = (recurrence.startDate.monthDay - 1) / 7; 110 StringBuilder sb = new StringBuilder(); 111 sb.append(r.getString(R.string.monthly)); 112 sb.append(" ("); 113 sb.append(mMonthRepeatByDayOfWeekStrs[weekday][dayNumber]); 114 sb.append(")"); 115 sb.append(endString); 116 return sb.toString(); 117 } 118 return r.getString(R.string.monthly) + endString; 119 } 120 case EventRecurrence.YEARLY: 121 return r.getString(R.string.yearly_plain) + endString; 122 } 123 124 return null; 125 } 126 cacheMonthRepeatStrings(Resources r, int weekday)127 private static void cacheMonthRepeatStrings(Resources r, int weekday) { 128 if (mMonthRepeatByDayOfWeekIds == null) { 129 mMonthRepeatByDayOfWeekIds = new int[7]; 130 mMonthRepeatByDayOfWeekIds[0] = R.array.repeat_by_nth_sun; 131 mMonthRepeatByDayOfWeekIds[1] = R.array.repeat_by_nth_mon; 132 mMonthRepeatByDayOfWeekIds[2] = R.array.repeat_by_nth_tues; 133 mMonthRepeatByDayOfWeekIds[3] = R.array.repeat_by_nth_wed; 134 mMonthRepeatByDayOfWeekIds[4] = R.array.repeat_by_nth_thurs; 135 mMonthRepeatByDayOfWeekIds[5] = R.array.repeat_by_nth_fri; 136 mMonthRepeatByDayOfWeekIds[6] = R.array.repeat_by_nth_sat; 137 } 138 if (mMonthRepeatByDayOfWeekStrs == null) { 139 mMonthRepeatByDayOfWeekStrs = new String[7][]; 140 } 141 if (mMonthRepeatByDayOfWeekStrs[weekday] == null) { 142 mMonthRepeatByDayOfWeekStrs[weekday] = 143 r.getStringArray(mMonthRepeatByDayOfWeekIds[weekday]); 144 } 145 } 146 147 /** 148 * Converts day of week to a String. 149 * @param day a EventRecurrence constant 150 * @return day of week as a string 151 */ dayToString(int day, int dayOfWeekLength)152 private static String dayToString(int day, int dayOfWeekLength) { 153 return DateUtils.getDayOfWeekString(dayToUtilDay(day), dayOfWeekLength); 154 } 155 156 /** 157 * Converts EventRecurrence's day of week to DateUtil's day of week. 158 * @param day of week as an EventRecurrence value 159 * @return day of week as a DateUtil value. 160 */ dayToUtilDay(int day)161 private static int dayToUtilDay(int day) { 162 switch (day) { 163 case EventRecurrence.SU: return Calendar.SUNDAY; 164 case EventRecurrence.MO: return Calendar.MONDAY; 165 case EventRecurrence.TU: return Calendar.TUESDAY; 166 case EventRecurrence.WE: return Calendar.WEDNESDAY; 167 case EventRecurrence.TH: return Calendar.THURSDAY; 168 case EventRecurrence.FR: return Calendar.FRIDAY; 169 case EventRecurrence.SA: return Calendar.SATURDAY; 170 default: throw new IllegalArgumentException("bad day argument: " + day); 171 } 172 } 173 } 174