/******************************************************************************* * Copyright (c) 2010 Denis Solonenko. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v2.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * Contributors: * Denis Solonenko - initial API and implementation ******************************************************************************/ package ru.orangesoftware.financisto2.recur; import java.text.ParseException; import java.util.*; import android.util.Log; import ru.orangesoftware.financisto2.R; import ru.orangesoftware.financisto2.datetime.DateUtils; import android.content.Context; import com.google.ical.values.RRule; public class Recurrence { // TODO ds: replace with time holder // only HH:mm:ss should be used in RRULE, not the date part private Calendar startDate; public RecurrencePattern pattern; public RecurrencePeriod period; public static Recurrence parse(String recurrence) { Recurrence r = new Recurrence(); String[] a = recurrence.split("~"); try { Date d = DateUtils.FORMAT_TIMESTAMP_ISO_8601.parse(a[0]); Calendar c = Calendar.getInstance(); c.setTime(d); r.startDate = c; } catch (ParseException e) { throw new RuntimeException(recurrence); } r.pattern = RecurrencePattern.parse(a[1]); r.period = RecurrencePeriod.parse(a[2]); return r; } public String stateToString() { StringBuilder sb = new StringBuilder(); sb.append(DateUtils.FORMAT_TIMESTAMP_ISO_8601.format(startDate.getTime())).append("~"); sb.append(pattern.stateToString()).append("~"); sb.append(period.stateToString()); return sb.toString(); } public static Recurrence noRecur() { Recurrence r = new Recurrence(); r.startDate = Calendar.getInstance(); r.pattern = RecurrencePattern.noRecur(); r.period = RecurrencePeriod.noEndDate(); return r; } public Calendar getStartDate() { return startDate; } public void updateStartDate(int y, int m, int d) { startDate.set(Calendar.YEAR, y); startDate.set(Calendar.MONTH, m); startDate.set(Calendar.DAY_OF_MONTH, d); } public void updateStartTime(int h, int m, int s) { startDate.set(Calendar.HOUR_OF_DAY, h); startDate.set(Calendar.MINUTE, m); startDate.set(Calendar.SECOND, s); startDate.set(Calendar.MILLISECOND, 0); } public List<Date> generateDates(Date start, Date end) { DateRecurrenceIterator ri = createIterator(start); List<Date> dates = new ArrayList<Date>(); while (ri.hasNext()) { Date nextDate = ri.next(); if (nextDate.after(end)) { break; } dates.add(nextDate); } return dates; } public DateRecurrenceIterator createIterator(Date now) { RRule rrule = createRRule(); try { Log.d("RRULE", "Creating iterator for "+rrule.toIcal()); if (now.before(startDate.getTime())) { now = startDate.getTime(); } Calendar c = Calendar.getInstance(); c.setTime(startDate.getTime()); //c.set(Calendar.HOUR_OF_DAY, startDate.get(Calendar.HOUR_OF_DAY)); //c.set(Calendar.MINUTE, startDate.get(Calendar.MINUTE)); //c.set(Calendar.SECOND, startDate.get(Calendar.SECOND)); c.set(Calendar.MILLISECOND, 0); return DateRecurrenceIterator.create(rrule, now, c.getTime()); } catch (ParseException e) { Log.w("RRULE", "Unable to create iterator for "+rrule.toIcal()); return DateRecurrenceIterator.empty(); } } private RRule createRRule() { if (pattern.frequency == RecurrenceFrequency.GEEKY) { try { HashMap<String, String> map = RecurrenceViewFactory.parseState(pattern.params); String rrule = map.get(RecurrenceViewFactory.P_INTERVAL); return new RRule("RRULE:"+rrule.toUpperCase()); } catch (ParseException e) { throw new IllegalArgumentException(pattern.params); } } else { RRule r = new RRule(); pattern.updateRRule(r); period.updateRRule(r, startDate); return r; } } public String toInfoString(Context context) { StringBuilder sb = new StringBuilder(); sb.append(context.getString(pattern.frequency.titleId)) .append(", ").append(context.getString(R.string.recur_repeat_starts_on)).append(": ") .append(DateUtils.getShortDateFormat(context).format(startDate.getTime())).append(" ") .append(DateUtils.getTimeFormat(context).format(startDate.getTime())); return sb.toString(); } }