// Copyright (C) 2006 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.ical.iter; import com.google.ical.util.DTBuilder; import com.google.ical.values.Weekday; import com.google.ical.values.WeekdayNum; import com.google.ical.values.DateValue; /** * a dumping ground for utility functions that don't fit anywhere else. * * @author mikesamuel+svn@gmail.com (Mike Samuel) */ class Util { /** * advances builder to the earliest day on or after builder that falls on * wkst. * @param builder non null. * @param wkst the day of the week that the week starts on */ static void rollToNextWeekStart(DTBuilder builder, Weekday wkst) { DateValue bd = builder.toDate(); builder.day += (7 - ((7 + (Weekday.valueOf(bd).javaDayNum - wkst.javaDayNum)) % 7)) % 7; builder.normalize(); } /** * the earliest day on or after d that falls on wkst. * @param wkst the day of the week that the week starts on */ static DateValue nextWeekStart(DateValue d, Weekday wkst) { DTBuilder builder = new DTBuilder(d); builder.day += (7 - ((7 + (Weekday.valueOf(d).javaDayNum - wkst.javaDayNum)) % 7)) % 7; return builder.toDate(); } /** returns a sorted unique copy of ints. */ static int[] uniquify(int[] ints) { return uniquify(ints, 0, ints.length); } /** returns a sorted unique copy of ints. */ static int[] uniquify(int[] ints, int start, int end) { IntSet iset = new IntSet(); for (int i = end; --i >= start;) { iset.add(ints[i]); } return iset.toIntArray(); } /** * given a weekday number, such as -1SU, returns the day of the month that it * falls on. * The weekday number may be refer to a week in the current month in some * contexts or a week in the current year in other contexts. * @param dow0 the day of week of the first day in the current year/month. * @param nDays the number of days in the current year/month. * In [28,29,30,31,365,366]. * @param weekNum -1SU in the example above. * @param d0 the number of days between the 1st day of the current * year/month and the current month. * @param nDaysInMonth the number of days in the current month. * @return 0 indicates no such day */ static int dayNumToDate(Weekday dow0, int nDays, int weekNum, Weekday dow, int d0, int nDaysInMonth) { // if dow is wednesday, then this is the date of the first wednesday int firstDateOfGivenDow = 1 + ((7 + dow.javaDayNum - dow0.javaDayNum) % 7); int date; if (weekNum > 0) { date = ((weekNum - 1) * 7) + firstDateOfGivenDow - d0; } else { // count weeks from end of month // calculate last day of the given dow. // Since nDays <= 366, this should be > nDays int lastDateOfGivenDow = firstDateOfGivenDow + (7 * 54); lastDateOfGivenDow -= 7 * ((lastDateOfGivenDow - nDays + 6) / 7); date = lastDateOfGivenDow + 7 * (weekNum + 1) - d0; } if (date <= 0 || date > nDaysInMonth) { return 0; } return date; } /** * Compute an absolute week number given a relative one. * The day number -1SU refers to the last Sunday, so if there are 5 Sundays * in a period that starts on dow0 with nDays, then -1SU is 5SU. * Depending on where its used it may refer to the last Sunday of the year * or of the month. * * @param weekdayNum -1SU in the example above. * @param dow0 the day of the week of the first day of the week or month. * One of the RRULE_WDAY_* constants. * @param nDays the number of days in the month or year. * @return an abolute week number, e.g. 5 in the example above. * Valid if in [1,53]. */ static int invertWeekdayNum( WeekdayNum weekdayNum, Weekday dow0, int nDays) { assert weekdayNum.num < 0; // how many are there of that week? return countInPeriod(weekdayNum.wday, dow0, nDays) + weekdayNum.num + 1; } /** * the number of occurences of dow in a period nDays long where the first day * of the period has day of week dow0. */ static int countInPeriod(Weekday dow, Weekday dow0, int nDays) { // Two cases // (1a) dow >= dow0: count === (nDays - (dow - dow0)) / 7 // (1b) dow < dow0: count === (nDays - (7 - dow0 - dow)) / 7 if (dow.javaDayNum >= dow0.javaDayNum) { return 1 + ((nDays - (dow.javaDayNum - dow0.javaDayNum) - 1) / 7); } else { return 1 + ((nDays - (7 - (dow0.javaDayNum - dow.javaDayNum)) - 1) / 7); } } private Util() { // uninstantiable } }