Utils.java revision 981874e61ecf29a96a77601a3172b2503b6537ee
1146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project/* 2146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 3146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 4146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * you may not use this file except in compliance with the License. 6146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * You may obtain a copy of the License at 7146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 8146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 10146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * See the License for the specific language governing permissions and 14146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * limitations under the License. 15146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 16146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 17146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpackage com.android.calendar; 18146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 19146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport static android.provider.Calendar.EVENT_BEGIN_TIME; 20e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan 21d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chanimport com.android.calendar.CalendarController.ViewType; 22d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan 23d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chanimport android.app.Activity; 24146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Context; 25146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Intent; 26e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chanimport android.content.SharedPreferences; 27ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport android.database.Cursor; 28a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErikimport android.database.MatrixCursor; 29ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport android.graphics.drawable.Drawable; 30ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport android.graphics.drawable.GradientDrawable; 311ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport android.net.Uri; 32d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chanimport android.os.Bundle; 33eb10fa8bee049e0052b5cb53dcfbdaccef9f2740Erikimport android.text.TextUtils; 34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.Time; 35a48b9d426236d8d26bd99602bf0a84315b3f1b09Erikimport android.util.CalendarUtils.TimeZoneUtils; 361ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport android.util.Log; 37146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashiimport java.util.Calendar; 391427657d0bf7e69b831aa495828f67b45b69fd99Erikimport java.util.Formatter; 401ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport java.util.List; 41ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport java.util.Map; 423ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tangimport java.util.TimeZone; 4356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi 44146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpublic class Utils { 453dc5e908a825b879978ba523d9099dc2255da9a5Erik private static final boolean DEBUG = true; 463dc5e908a825b879978ba523d9099dc2255da9a5Erik private static final String TAG = "CalUtils"; 47bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan // Set to 0 until we have UI to perform undo 48bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan public static final long UNDO_DELAY = 0; 49bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 5079f228124de7d98146ca526d743436f6419e2365Erik // For recurring events which instances of the series are being modified 5179f228124de7d98146ca526d743436f6419e2365Erik public static final int MODIFY_UNINITIALIZED = 0; 5279f228124de7d98146ca526d743436f6419e2365Erik public static final int MODIFY_SELECTED = 1; 5379f228124de7d98146ca526d743436f6419e2365Erik public static final int MODIFY_ALL_FOLLOWING = 2; 5479f228124de7d98146ca526d743436f6419e2365Erik public static final int MODIFY_ALL = 3; 5579f228124de7d98146ca526d743436f6419e2365Erik 567b92da258a480284dcc15a518ea570072329a31dErik // When the edit event view finishes it passes back the appropriate exit 577b92da258a480284dcc15a518ea570072329a31dErik // code. 587b92da258a480284dcc15a518ea570072329a31dErik public static final int DONE_REVERT = 1 << 0; 597b92da258a480284dcc15a518ea570072329a31dErik public static final int DONE_SAVE = 1 << 1; 607b92da258a480284dcc15a518ea570072329a31dErik public static final int DONE_DELETE = 1 << 2; 617b92da258a480284dcc15a518ea570072329a31dErik // And should re run with DONE_EXIT if it should also leave the view, just 627b92da258a480284dcc15a518ea570072329a31dErik // exiting is identical to reverting 637b92da258a480284dcc15a518ea570072329a31dErik public static final int DONE_EXIT = 1 << 0; 6479f228124de7d98146ca526d743436f6419e2365Erik 65ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan private static final int CLEAR_ALPHA_MASK = 0x00FFFFFF; 66ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan private static final int HIGH_ALPHA = 255 << 24; 67ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan private static final int MED_ALPHA = 180 << 24; 68ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan private static final int LOW_ALPHA = 150 << 24; 69ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan 70ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan protected static final String OPEN_EMAIL_MARKER = " <"; 71ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan protected static final String CLOSE_EMAIL_MARKER = ">"; 72ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan /* The corner should be rounded on the top right and bottom right */ 737b92da258a480284dcc15a518ea570072329a31dErik private static final float[] CORNERS = new float[] { 0, 0, 5, 5, 5, 5, 0, 0 }; 74ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan 75d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan public static final String INTENT_KEY_DETAIL_VIEW = "DETAIL_VIEW"; 76d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan public static final String INTENT_KEY_VIEW_TYPE = "VIEW"; 77d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan public static final String INTENT_VALUE_VIEW_TYPE_DAY = "DAY"; 78275232dae58bb24e3360a779ada9d24601a99bcfErik 79981874e61ecf29a96a77601a3172b2503b6537eeErik public static final int MONDAY_BEFORE_JULIAN_EPOCH = Time.EPOCH_JULIAN_DAY - 3; 80981874e61ecf29a96a77601a3172b2503b6537eeErik 81a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik // The name of the shared preferences file. This name must be maintained for 82a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik // historical 83a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik // reasons, as it's what PreferenceManager assigned the first time the file 84a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik // was created. 85a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik private static final String SHARED_PREFS_NAME = "com.android.calendar_preferences"; 8635d1362a75eac7cebbe9de23d08fea08c4aac817Erik 87a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik private static final TimeZoneUtils mTZUtils = new TimeZoneUtils(SHARED_PREFS_NAME); 88d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan 89d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan public static int getViewTypeFromIntentAndSharedPref(Activity activity) { 90dd95df57c8c5a58a85c4c0effad5652dec14f621Erik Intent intent = activity.getIntent(); 91dd95df57c8c5a58a85c4c0effad5652dec14f621Erik Bundle extras = intent.getExtras(); 924b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(activity); 93d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan 947b92da258a480284dcc15a518ea570072329a31dErik if (TextUtils.equals(intent.getAction(), Intent.ACTION_EDIT)) { 95dd95df57c8c5a58a85c4c0effad5652dec14f621Erik return ViewType.EDIT; 96dd95df57c8c5a58a85c4c0effad5652dec14f621Erik } 97d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan if (extras != null) { 98d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan if (extras.getBoolean(INTENT_KEY_DETAIL_VIEW, false)) { 99d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan // This is the "detail" view which is either agenda or day view 1004b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa return prefs.getInt(GeneralPreferences.KEY_DETAILED_VIEW, 1014b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa GeneralPreferences.DEFAULT_DETAILED_VIEW); 102d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan } else if (INTENT_VALUE_VIEW_TYPE_DAY.equals(extras.getString(INTENT_KEY_VIEW_TYPE))) { 103d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan // Not sure who uses this. This logic came from LaunchActivity 104d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan return ViewType.DAY; 105d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan } 106d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan } 107d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan 108d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan // Default to the last view 1097b92da258a480284dcc15a518ea570072329a31dErik return prefs.getInt( 1107b92da258a480284dcc15a518ea570072329a31dErik GeneralPreferences.KEY_START_VIEW, GeneralPreferences.DEFAULT_START_VIEW); 111d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan } 112ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan 113235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik /** 1147b92da258a480284dcc15a518ea570072329a31dErik * Writes a new home time zone to the db. Updates the home time zone in the 1157b92da258a480284dcc15a518ea570072329a31dErik * db asynchronously and updates the local cache. Sending a time zone of 1167b92da258a480284dcc15a518ea570072329a31dErik * **tbd** will cause it to be set to the device's time zone. null or empty 1177b92da258a480284dcc15a518ea570072329a31dErik * tz will be ignored. 1183dc5e908a825b879978ba523d9099dc2255da9a5Erik * 1193dc5e908a825b879978ba523d9099dc2255da9a5Erik * @param context The calling activity 1203dc5e908a825b879978ba523d9099dc2255da9a5Erik * @param timeZone The time zone to set Calendar to, or **tbd** 1213dc5e908a825b879978ba523d9099dc2255da9a5Erik */ 1223dc5e908a825b879978ba523d9099dc2255da9a5Erik public static void setTimeZone(Context context, String timeZone) { 123a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik mTZUtils.setTimeZone(context, timeZone); 1243dc5e908a825b879978ba523d9099dc2255da9a5Erik } 1253dc5e908a825b879978ba523d9099dc2255da9a5Erik 1263dc5e908a825b879978ba523d9099dc2255da9a5Erik /** 1277b92da258a480284dcc15a518ea570072329a31dErik * Gets the time zone that Calendar should be displayed in This is a helper 1287b92da258a480284dcc15a518ea570072329a31dErik * method to get the appropriate time zone for Calendar. If this is the 1297b92da258a480284dcc15a518ea570072329a31dErik * first time this method has been called it will initiate an asynchronous 1307b92da258a480284dcc15a518ea570072329a31dErik * query to verify that the data in preferences is correct. The callback 1317b92da258a480284dcc15a518ea570072329a31dErik * supplied will only be called if this query returns a value other than 1327b92da258a480284dcc15a518ea570072329a31dErik * what is stored in preferences and should cause the calling activity to 1337b92da258a480284dcc15a518ea570072329a31dErik * refresh anything that depends on calling this method. 134235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik * 135235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik * @param context The calling activity 1367b92da258a480284dcc15a518ea570072329a31dErik * @param callback The runnable that should execute if a query returns new 1377b92da258a480284dcc15a518ea570072329a31dErik * values 1387b92da258a480284dcc15a518ea570072329a31dErik * @return The string value representing the time zone Calendar should 1397b92da258a480284dcc15a518ea570072329a31dErik * display 140235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik */ 141235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik public static String getTimeZone(Context context, Runnable callback) { 142a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik return mTZUtils.getTimeZone(context, callback); 14345efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan } 14445efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan 1451427657d0bf7e69b831aa495828f67b45b69fd99Erik /** 1461427657d0bf7e69b831aa495828f67b45b69fd99Erik * Formats a date or a time range according to the local conventions. 1471427657d0bf7e69b831aa495828f67b45b69fd99Erik * 1481427657d0bf7e69b831aa495828f67b45b69fd99Erik * @param context the context is required only if the time is shown 1491427657d0bf7e69b831aa495828f67b45b69fd99Erik * @param startMillis the start time in UTC milliseconds 1501427657d0bf7e69b831aa495828f67b45b69fd99Erik * @param endMillis the end time in UTC milliseconds 1517b92da258a480284dcc15a518ea570072329a31dErik * @param flags a bit mask of options See {@link #formatDateRange(Context, 1527b92da258a480284dcc15a518ea570072329a31dErik * Formatter, long, long, int, String) formatDateRange} 1531427657d0bf7e69b831aa495828f67b45b69fd99Erik * @return a string containing the formatted date/time range. 1541427657d0bf7e69b831aa495828f67b45b69fd99Erik */ 1557b92da258a480284dcc15a518ea570072329a31dErik public static String formatDateRange( 1567b92da258a480284dcc15a518ea570072329a31dErik Context context, long startMillis, long endMillis, int flags) { 157a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik return mTZUtils.formatDateRange(context, startMillis, endMillis, flags); 158a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik } 159a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik 160a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik public static String getSharedPreference(Context context, String key, String defaultValue) { 161a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 162a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik return prefs.getString(key, defaultValue); 1631427657d0bf7e69b831aa495828f67b45b69fd99Erik } 1641427657d0bf7e69b831aa495828f67b45b69fd99Erik 165d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan public static int getSharedPreference(Context context, String key, int defaultValue) { 1664b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 167d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan return prefs.getInt(key, defaultValue); 168d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan } 169d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan 170f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang /** 171f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang * Asynchronously sets the preference with the given key to the given value 172f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang * 173f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang * @param context the context to use to get preferences from 174f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang * @param key the key of the preference to set 175f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang * @param value the value to set 176f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang */ 177fbce65e53c7a111955f638db5bf8bee35381e5b7Erik public static void setSharedPreference(Context context, String key, String value) { 1784b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 17924fac46d6b87ce21d5e6a4b1c0fdcaa83d408997Brad Fitzpatrick prefs.edit().putString(key, value).apply(); 18045efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan } 18145efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan 1823dc5e908a825b879978ba523d9099dc2255da9a5Erik static void setSharedPreference(Context context, String key, boolean value) { 1834b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 1843dc5e908a825b879978ba523d9099dc2255da9a5Erik SharedPreferences.Editor editor = prefs.edit(); 1853dc5e908a825b879978ba523d9099dc2255da9a5Erik editor.putBoolean(key, value); 186275232dae58bb24e3360a779ada9d24601a99bcfErik editor.apply(); 1873dc5e908a825b879978ba523d9099dc2255da9a5Erik } 1883dc5e908a825b879978ba523d9099dc2255da9a5Erik 189d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan /** 190d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan * Save default agenda/day/week/month view for next time 191d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan * 192d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan * @param context 193d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan * @param viewId {@link CalendarController.ViewType} 194d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan */ 195e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan static void setDefaultView(Context context, int viewId) { 1964b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 197e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan SharedPreferences.Editor editor = prefs.edit(); 198f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang 199d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan if (viewId == CalendarController.ViewType.AGENDA 200d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan || viewId == CalendarController.ViewType.DAY) { 201e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan // Record the (new) detail start view only for Agenda and Day 2024b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa editor.putInt(GeneralPreferences.KEY_DETAILED_VIEW, viewId); 203e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan } 204e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan 205e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan // Record the (new) start view 2064b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa editor.putInt(GeneralPreferences.KEY_START_VIEW, viewId); 20724fac46d6b87ce21d5e6a4b1c0fdcaa83d408997Brad Fitzpatrick editor.apply(); 208e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan } 209e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan 210a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik public static MatrixCursor matrixCursorFromCursor(Cursor cursor) { 211a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames()); 212a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik int numColumns = cursor.getColumnCount(); 213a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik String data[] = new String[numColumns]; 214a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik cursor.moveToPosition(-1); 215a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik while (cursor.moveToNext()) { 216a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik for (int i = 0; i < numColumns; i++) { 217a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik data[i] = cursor.getString(i); 218a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 219a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik newCursor.addRow(data); 220a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 221a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return newCursor; 222a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 223a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 224a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik /** 225a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik * Compares two cursors to see if they contain the same data. 226a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik * 2277b92da258a480284dcc15a518ea570072329a31dErik * @return Returns true of the cursors contain the same data and are not 2287b92da258a480284dcc15a518ea570072329a31dErik * null, false otherwise 229a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik */ 230a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik public static boolean compareCursors(Cursor c1, Cursor c2) { 2317b92da258a480284dcc15a518ea570072329a31dErik if (c1 == null || c2 == null) { 232a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return false; 233a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 234a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 235a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik int numColumns = c1.getColumnCount(); 236a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik if (numColumns != c2.getColumnCount()) { 237a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return false; 238a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 239a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 240a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik if (c1.getCount() != c2.getCount()) { 241a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return false; 242a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 243a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 244a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik c1.moveToPosition(-1); 245a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik c2.moveToPosition(-1); 2467b92da258a480284dcc15a518ea570072329a31dErik while (c1.moveToNext() && c2.moveToNext()) { 2477b92da258a480284dcc15a518ea570072329a31dErik for (int i = 0; i < numColumns; i++) { 2487b92da258a480284dcc15a518ea570072329a31dErik if (!TextUtils.equals(c1.getString(i), c2.getString(i))) { 249a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return false; 250a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 251a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 252a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 253a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 254a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return true; 255a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 256a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * If the given intent specifies a time (in milliseconds since the epoch), 259146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * then that time is returned. Otherwise, the current time is returned. 260146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 261146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public static final long timeFromIntentInMillis(Intent intent) { 2627b92da258a480284dcc15a518ea570072329a31dErik // If the time was specified, then use that. Otherwise, use the current 2637b92da258a480284dcc15a518ea570072329a31dErik // time. 2641ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik Uri data = intent.getData(); 265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = intent.getLongExtra(EVENT_BEGIN_TIME, -1); 2661ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik if (millis == -1 && data != null && data.isHierarchical()) { 2671ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik List<String> path = data.getPathSegments(); 2687b92da258a480284dcc15a518ea570072329a31dErik if (path.size() == 2 && path.get(0).equals("time")) { 2691ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik try { 2701ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik millis = Long.valueOf(data.getLastPathSegment()); 2711ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik } catch (NumberFormatException e) { 2727b92da258a480284dcc15a518ea570072329a31dErik Log.i("Calendar", "timeFromIntentInMillis: Data existed but no valid time " 2737b92da258a480284dcc15a518ea570072329a31dErik + "found. Using current time."); 2741ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik } 2751ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik } 2761ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik } 27776727b7a9cf780f200414548b9d454bf9a701e3eErik if (millis <= 0) { 278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project millis = System.currentTimeMillis(); 279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return millis; 281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 283ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan public static Drawable getColorChip(int color) { 284ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan /* 2857b92da258a480284dcc15a518ea570072329a31dErik * We want the color chip to have a nice gradient using the color of the 2867b92da258a480284dcc15a518ea570072329a31dErik * calendar. To do this we use a GradientDrawable. The color supplied 2877b92da258a480284dcc15a518ea570072329a31dErik * has an alpha of FF so we first do: color & 0x00FFFFFF to clear the 2887b92da258a480284dcc15a518ea570072329a31dErik * alpha. Then we add our alpha to it. We use 3 colors to get a step 2897b92da258a480284dcc15a518ea570072329a31dErik * effect where it starts off very light and quickly becomes dark and 2907b92da258a480284dcc15a518ea570072329a31dErik * then a slow transition to be even darker. 291ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan */ 292ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan color &= CLEAR_ALPHA_MASK; 293ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan int startColor = color | HIGH_ALPHA; 294ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan int middleColor = color | MED_ALPHA; 295ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan int endColor = color | LOW_ALPHA; 2967b92da258a480284dcc15a518ea570072329a31dErik int[] colors = new int[] { startColor, middleColor, endColor }; 297ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan GradientDrawable d = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors); 298ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan d.setCornerRadii(CORNERS); 299ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan return d; 300ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan } 301ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan 302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 3037b92da258a480284dcc15a518ea570072329a31dErik * Formats the given Time object so that it gives the month and year (for 3047b92da258a480284dcc15a518ea570072329a31dErik * example, "September 2007"). 305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param time the time to format 307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @return the string containing the weekday and the date 308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 309ad36a3c3cde7a2ec6d3a35d2529d46f03bd8d59dMichael Chan public static String formatMonthYear(Context context, Time time) { 310ad36a3c3cde7a2ec6d3a35d2529d46f03bd8d59dMichael Chan return time.format(context.getResources().getString(R.string.month_year)); 311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 3144c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * Returns a list joined together by the provided delimiter, for example, 3154c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * ["a", "b", "c"] could be joined into "a,b,c" 3164c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * 3174c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * @param things the things to join together 3184c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * @param delim the delimiter to use 3194c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * @return a string contained the things joined together 3204c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang */ 3214c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang public static String join(List<?> things, String delim) { 3224c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang StringBuilder builder = new StringBuilder(); 3234c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang boolean first = true; 3244c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang for (Object thing : things) { 3254c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang if (first) { 3264c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang first = false; 3274c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang } else { 3284c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang builder.append(delim); 3294c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang } 3304c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang builder.append(thing.toString()); 3314c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang } 3324c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang return builder.toString(); 3334c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang } 3344c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang 3354c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang /** 336981874e61ecf29a96a77601a3172b2503b6537eeErik * Returns the week since {@link Time#EPOCH_JULIAN_DAY} (Jan 1, 1970) 337981874e61ecf29a96a77601a3172b2503b6537eeErik * adjusted for first day of week. 338981874e61ecf29a96a77601a3172b2503b6537eeErik * 339981874e61ecf29a96a77601a3172b2503b6537eeErik * This takes a julian day and the week start day and calculates which 340981874e61ecf29a96a77601a3172b2503b6537eeErik * week since {@link Time#EPOCH_JULIAN_DAY} that day occurs in, starting 341981874e61ecf29a96a77601a3172b2503b6537eeErik * at 0. *Do not* use this to compute the ISO week number for the year. 342981874e61ecf29a96a77601a3172b2503b6537eeErik * 343981874e61ecf29a96a77601a3172b2503b6537eeErik * @param julianDay The julian day to calculate the week number for 344981874e61ecf29a96a77601a3172b2503b6537eeErik * @param firstDayOfWeek Which week day is the first day of the week, 345981874e61ecf29a96a77601a3172b2503b6537eeErik * see {@link Time#SUNDAY} 346981874e61ecf29a96a77601a3172b2503b6537eeErik * @return Weeks since the epoch 347981874e61ecf29a96a77601a3172b2503b6537eeErik */ 348981874e61ecf29a96a77601a3172b2503b6537eeErik public static int getWeeksSinceEpochFromJulianDay(int julianDay, int firstDayOfWeek) { 349981874e61ecf29a96a77601a3172b2503b6537eeErik int diff = Time.THURSDAY - firstDayOfWeek; 350981874e61ecf29a96a77601a3172b2503b6537eeErik if (diff < 0) { 351981874e61ecf29a96a77601a3172b2503b6537eeErik diff += 7; 352981874e61ecf29a96a77601a3172b2503b6537eeErik } 353981874e61ecf29a96a77601a3172b2503b6537eeErik int refDay = Time.EPOCH_JULIAN_DAY - diff; 354981874e61ecf29a96a77601a3172b2503b6537eeErik return (julianDay - refDay) / 7; 355981874e61ecf29a96a77601a3172b2503b6537eeErik } 356981874e61ecf29a96a77601a3172b2503b6537eeErik 357981874e61ecf29a96a77601a3172b2503b6537eeErik /** 358981874e61ecf29a96a77601a3172b2503b6537eeErik * Takes a number of weeks since the epoch and calculates the Julian day of 359981874e61ecf29a96a77601a3172b2503b6537eeErik * the Monday for that week. 360981874e61ecf29a96a77601a3172b2503b6537eeErik * 361981874e61ecf29a96a77601a3172b2503b6537eeErik * This assumes that the week containing the {@link Time#EPOCH_JULIAN_DAY} 362981874e61ecf29a96a77601a3172b2503b6537eeErik * is considered week 0. It returns the Julian day for the Monday 363981874e61ecf29a96a77601a3172b2503b6537eeErik * {@code week} weeks after the Monday of the week containing the epoch. 364981874e61ecf29a96a77601a3172b2503b6537eeErik * 365981874e61ecf29a96a77601a3172b2503b6537eeErik * @param week Number of weeks since the epoch 366981874e61ecf29a96a77601a3172b2503b6537eeErik * @return The julian day for the Monday of the given week since the epoch 367981874e61ecf29a96a77601a3172b2503b6537eeErik */ 368981874e61ecf29a96a77601a3172b2503b6537eeErik public static int getJulianMondayFromWeeksSinceEpoch(int week) { 369981874e61ecf29a96a77601a3172b2503b6537eeErik return MONDAY_BEFORE_JULIAN_EPOCH + week * 7; 370981874e61ecf29a96a77601a3172b2503b6537eeErik } 371981874e61ecf29a96a77601a3172b2503b6537eeErik 372981874e61ecf29a96a77601a3172b2503b6537eeErik /** 37356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * Get first day of week as android.text.format.Time constant. 3747b92da258a480284dcc15a518ea570072329a31dErik * 37556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @return the first day of week in android.text.format.Time 37656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi */ 3778e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang public static int getFirstDayOfWeek(Context context) { 3784b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 3797b92da258a480284dcc15a518ea570072329a31dErik String pref = prefs.getString( 3807b92da258a480284dcc15a518ea570072329a31dErik GeneralPreferences.KEY_WEEK_START_DAY, GeneralPreferences.WEEK_START_DEFAULT); 3818e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang 3828e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang int startDay; 3834b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa if (GeneralPreferences.WEEK_START_DEFAULT.equals(pref)) { 3848e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang startDay = Calendar.getInstance().getFirstDayOfWeek(); 3858e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang } else { 3868e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang startDay = Integer.parseInt(pref); 3878e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang } 3888e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang 38956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi if (startDay == Calendar.SATURDAY) { 39056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi return Time.SATURDAY; 39156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } else if (startDay == Calendar.MONDAY) { 39256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi return Time.MONDAY; 39356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } else { 39456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi return Time.SUNDAY; 39556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } 39656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } 39756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi 39856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi /** 399981874e61ecf29a96a77601a3172b2503b6537eeErik * Get first day of week as android.text.format.Time constant. 400981874e61ecf29a96a77601a3172b2503b6537eeErik * 401981874e61ecf29a96a77601a3172b2503b6537eeErik * @return the first day of week in android.text.format.Time 402981874e61ecf29a96a77601a3172b2503b6537eeErik */ 403981874e61ecf29a96a77601a3172b2503b6537eeErik public static boolean getShowWeekNumber(Context context) { 404981874e61ecf29a96a77601a3172b2503b6537eeErik SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 405981874e61ecf29a96a77601a3172b2503b6537eeErik return prefs.getBoolean( 406981874e61ecf29a96a77601a3172b2503b6537eeErik GeneralPreferences.KEY_SHOW_WEEK_NUM, GeneralPreferences.DEFAULT_SHOW_WEEK_NUM); 407981874e61ecf29a96a77601a3172b2503b6537eeErik } 408981874e61ecf29a96a77601a3172b2503b6537eeErik 409981874e61ecf29a96a77601a3172b2503b6537eeErik /** 41056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * Determine whether the column position is Saturday or not. 4117b92da258a480284dcc15a518ea570072329a31dErik * 41256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @param column the column position 41356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @param firstDayOfWeek the first day of week in android.text.format.Time 41456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @return true if the column is Saturday position 41556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi */ 41656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi public static boolean isSaturday(int column, int firstDayOfWeek) { 41756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi return (firstDayOfWeek == Time.SUNDAY && column == 6) 4187b92da258a480284dcc15a518ea570072329a31dErik || (firstDayOfWeek == Time.MONDAY && column == 5) 4197b92da258a480284dcc15a518ea570072329a31dErik || (firstDayOfWeek == Time.SATURDAY && column == 0); 42056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } 42156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi 42256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi /** 42356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * Determine whether the column position is Sunday or not. 4247b92da258a480284dcc15a518ea570072329a31dErik * 42556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @param column the column position 42656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @param firstDayOfWeek the first day of week in android.text.format.Time 42756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @return true if the column is Sunday position 42856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi */ 42956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi public static boolean isSunday(int column, int firstDayOfWeek) { 43056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi return (firstDayOfWeek == Time.SUNDAY && column == 0) 4317b92da258a480284dcc15a518ea570072329a31dErik || (firstDayOfWeek == Time.MONDAY && column == 6) 4327b92da258a480284dcc15a518ea570072329a31dErik || (firstDayOfWeek == Time.SATURDAY && column == 1); 43356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } 434ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan 435ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan /** 4363ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang * Convert given UTC time into current local time. 4373ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang * 4383ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang * @param recycle Time object to recycle, otherwise null. 4393ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang * @param utcTime Time to convert, in UTC. 4403ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang */ 4413ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang public static long convertUtcToLocal(Time recycle, long utcTime) { 4423ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang if (recycle == null) { 4433ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang recycle = new Time(); 4443ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang } 4453ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang recycle.timezone = Time.TIMEZONE_UTC; 4463ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang recycle.set(utcTime); 4473ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang recycle.timezone = TimeZone.getDefault().getID(); 4483ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang return recycle.normalize(true); 4493ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang } 4503ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang 4513ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang /** 452ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan * Scan through a cursor of calendars and check if names are duplicated. 4537b92da258a480284dcc15a518ea570072329a31dErik * This travels a cursor containing calendar display names and fills in the 4547b92da258a480284dcc15a518ea570072329a31dErik * provided map with whether or not each name is repeated. 455ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan * 456ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan * @param isDuplicateName The map to put the duplicate check results in. 457ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan * @param cursor The query of calendars to check 458ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan * @param nameIndex The column of the query that contains the display name 459ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan */ 4607b92da258a480284dcc15a518ea570072329a31dErik public static void checkForDuplicateNames( 4617b92da258a480284dcc15a518ea570072329a31dErik Map<String, Boolean> isDuplicateName, Cursor cursor, int nameIndex) { 462ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan isDuplicateName.clear(); 463ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan cursor.moveToPosition(-1); 464ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan while (cursor.moveToNext()) { 465ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan String displayName = cursor.getString(nameIndex); 466ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan // Set it to true if we've seen this name before, false otherwise 467ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan if (displayName != null) { 468ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan isDuplicateName.put(displayName, isDuplicateName.containsKey(displayName)); 469ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan } 470ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan } 471ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan } 4729138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang 4739138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang /** 4749138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang * Null-safe object comparison 4757b92da258a480284dcc15a518ea570072329a31dErik * 4769138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang * @param s1 4779138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang * @param s2 4789138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang * @return 4799138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang */ 4809138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang public static boolean equals(Object o1, Object o2) { 4819138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang return o1 == null ? o2 == null : o1.equals(o2); 4829138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang } 483146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project} 484