Utils.java revision 82400dd70331df7885dd59b809c4bc0667046320
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; 275b2a907fa3a983f74bb48da86846e351c2a464d0Isaac Katzenelsonimport android.content.res.Configuration; 28ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport android.database.Cursor; 29a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErikimport android.database.MatrixCursor; 301ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport android.net.Uri; 31d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chanimport android.os.Bundle; 32eb10fa8bee049e0052b5cb53dcfbdaccef9f2740Erikimport android.text.TextUtils; 3329190975b9238dd6841f822f82f2fb83b0557f36Daisuke Miyakawaimport android.text.format.DateUtils; 34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.Time; 35a48b9d426236d8d26bd99602bf0a84315b3f1b09Erikimport android.util.CalendarUtils.TimeZoneUtils; 361ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport android.util.Log; 37146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelsonimport java.util.ArrayList; 3956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashiimport java.util.Calendar; 401427657d0bf7e69b831aa495828f67b45b69fd99Erikimport java.util.Formatter; 4182400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelsonimport java.util.Iterator; 421ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport java.util.List; 43ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport java.util.Map; 4456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi 45146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpublic class Utils { 463dc5e908a825b879978ba523d9099dc2255da9a5Erik private static final boolean DEBUG = true; 473dc5e908a825b879978ba523d9099dc2255da9a5Erik private static final String TAG = "CalUtils"; 48bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan // Set to 0 until we have UI to perform undo 49bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan public static final long UNDO_DELAY = 0; 50bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 5179f228124de7d98146ca526d743436f6419e2365Erik // For recurring events which instances of the series are being modified 5279f228124de7d98146ca526d743436f6419e2365Erik public static final int MODIFY_UNINITIALIZED = 0; 5379f228124de7d98146ca526d743436f6419e2365Erik public static final int MODIFY_SELECTED = 1; 5479f228124de7d98146ca526d743436f6419e2365Erik public static final int MODIFY_ALL_FOLLOWING = 2; 5579f228124de7d98146ca526d743436f6419e2365Erik public static final int MODIFY_ALL = 3; 5679f228124de7d98146ca526d743436f6419e2365Erik 577b92da258a480284dcc15a518ea570072329a31dErik // When the edit event view finishes it passes back the appropriate exit 587b92da258a480284dcc15a518ea570072329a31dErik // code. 597b92da258a480284dcc15a518ea570072329a31dErik public static final int DONE_REVERT = 1 << 0; 607b92da258a480284dcc15a518ea570072329a31dErik public static final int DONE_SAVE = 1 << 1; 617b92da258a480284dcc15a518ea570072329a31dErik public static final int DONE_DELETE = 1 << 2; 627b92da258a480284dcc15a518ea570072329a31dErik // And should re run with DONE_EXIT if it should also leave the view, just 637b92da258a480284dcc15a518ea570072329a31dErik // exiting is identical to reverting 647b92da258a480284dcc15a518ea570072329a31dErik public static final int DONE_EXIT = 1 << 0; 6579f228124de7d98146ca526d743436f6419e2365Erik 66ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan protected static final String OPEN_EMAIL_MARKER = " <"; 67ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan protected static final String CLOSE_EMAIL_MARKER = ">"; 68ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan 69d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan public static final String INTENT_KEY_DETAIL_VIEW = "DETAIL_VIEW"; 70d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan public static final String INTENT_KEY_VIEW_TYPE = "VIEW"; 71d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan public static final String INTENT_VALUE_VIEW_TYPE_DAY = "DAY"; 72275232dae58bb24e3360a779ada9d24601a99bcfErik 73981874e61ecf29a96a77601a3172b2503b6537eeErik public static final int MONDAY_BEFORE_JULIAN_EPOCH = Time.EPOCH_JULIAN_DAY - 3; 74981874e61ecf29a96a77601a3172b2503b6537eeErik 75a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik // The name of the shared preferences file. This name must be maintained for 76a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik // historical 77a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik // reasons, as it's what PreferenceManager assigned the first time the file 78a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik // was created. 79a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik private static final String SHARED_PREFS_NAME = "com.android.calendar_preferences"; 8035d1362a75eac7cebbe9de23d08fea08c4aac817Erik 81a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik private static final TimeZoneUtils mTZUtils = new TimeZoneUtils(SHARED_PREFS_NAME); 82b60218a31d948ea0a549daf6464063d20b48421fMichael Chan private static boolean mAllowWeekForDetailView = false; 83ca4786769151f97069980443ce43d9c4f867ac5bErik private static long mTardis = 0; 84d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan 85d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan public static int getViewTypeFromIntentAndSharedPref(Activity activity) { 86dd95df57c8c5a58a85c4c0effad5652dec14f621Erik Intent intent = activity.getIntent(); 87dd95df57c8c5a58a85c4c0effad5652dec14f621Erik Bundle extras = intent.getExtras(); 884b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(activity); 89d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan 907b92da258a480284dcc15a518ea570072329a31dErik if (TextUtils.equals(intent.getAction(), Intent.ACTION_EDIT)) { 91dd95df57c8c5a58a85c4c0effad5652dec14f621Erik return ViewType.EDIT; 92dd95df57c8c5a58a85c4c0effad5652dec14f621Erik } 93d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan if (extras != null) { 94d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan if (extras.getBoolean(INTENT_KEY_DETAIL_VIEW, false)) { 95d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan // This is the "detail" view which is either agenda or day view 964b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa return prefs.getInt(GeneralPreferences.KEY_DETAILED_VIEW, 974b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa GeneralPreferences.DEFAULT_DETAILED_VIEW); 98d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan } else if (INTENT_VALUE_VIEW_TYPE_DAY.equals(extras.getString(INTENT_KEY_VIEW_TYPE))) { 99d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan // Not sure who uses this. This logic came from LaunchActivity 100d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan return ViewType.DAY; 101d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan } 102d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan } 103d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan 104d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan // Default to the last view 1057b92da258a480284dcc15a518ea570072329a31dErik return prefs.getInt( 1067b92da258a480284dcc15a518ea570072329a31dErik GeneralPreferences.KEY_START_VIEW, GeneralPreferences.DEFAULT_START_VIEW); 107d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan } 108ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan 109235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik /** 1107b92da258a480284dcc15a518ea570072329a31dErik * Writes a new home time zone to the db. Updates the home time zone in the 1117b92da258a480284dcc15a518ea570072329a31dErik * db asynchronously and updates the local cache. Sending a time zone of 1127b92da258a480284dcc15a518ea570072329a31dErik * **tbd** will cause it to be set to the device's time zone. null or empty 1137b92da258a480284dcc15a518ea570072329a31dErik * tz will be ignored. 1143dc5e908a825b879978ba523d9099dc2255da9a5Erik * 1153dc5e908a825b879978ba523d9099dc2255da9a5Erik * @param context The calling activity 1163dc5e908a825b879978ba523d9099dc2255da9a5Erik * @param timeZone The time zone to set Calendar to, or **tbd** 1173dc5e908a825b879978ba523d9099dc2255da9a5Erik */ 1183dc5e908a825b879978ba523d9099dc2255da9a5Erik public static void setTimeZone(Context context, String timeZone) { 119a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik mTZUtils.setTimeZone(context, timeZone); 1203dc5e908a825b879978ba523d9099dc2255da9a5Erik } 1213dc5e908a825b879978ba523d9099dc2255da9a5Erik 1223dc5e908a825b879978ba523d9099dc2255da9a5Erik /** 1237b92da258a480284dcc15a518ea570072329a31dErik * Gets the time zone that Calendar should be displayed in This is a helper 1247b92da258a480284dcc15a518ea570072329a31dErik * method to get the appropriate time zone for Calendar. If this is the 1257b92da258a480284dcc15a518ea570072329a31dErik * first time this method has been called it will initiate an asynchronous 1267b92da258a480284dcc15a518ea570072329a31dErik * query to verify that the data in preferences is correct. The callback 1277b92da258a480284dcc15a518ea570072329a31dErik * supplied will only be called if this query returns a value other than 1287b92da258a480284dcc15a518ea570072329a31dErik * what is stored in preferences and should cause the calling activity to 1297b92da258a480284dcc15a518ea570072329a31dErik * refresh anything that depends on calling this method. 130235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik * 131235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik * @param context The calling activity 1327b92da258a480284dcc15a518ea570072329a31dErik * @param callback The runnable that should execute if a query returns new 1337b92da258a480284dcc15a518ea570072329a31dErik * values 1347b92da258a480284dcc15a518ea570072329a31dErik * @return The string value representing the time zone Calendar should 1357b92da258a480284dcc15a518ea570072329a31dErik * display 136235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik */ 137235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik public static String getTimeZone(Context context, Runnable callback) { 138a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik return mTZUtils.getTimeZone(context, callback); 13945efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan } 14045efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan 1411427657d0bf7e69b831aa495828f67b45b69fd99Erik /** 1421427657d0bf7e69b831aa495828f67b45b69fd99Erik * Formats a date or a time range according to the local conventions. 1431427657d0bf7e69b831aa495828f67b45b69fd99Erik * 1441427657d0bf7e69b831aa495828f67b45b69fd99Erik * @param context the context is required only if the time is shown 1451427657d0bf7e69b831aa495828f67b45b69fd99Erik * @param startMillis the start time in UTC milliseconds 1461427657d0bf7e69b831aa495828f67b45b69fd99Erik * @param endMillis the end time in UTC milliseconds 14729190975b9238dd6841f822f82f2fb83b0557f36Daisuke Miyakawa * @param flags a bit mask of options See {@link DateUtils#formatDateRange(Context, Formatter, 14829190975b9238dd6841f822f82f2fb83b0557f36Daisuke Miyakawa * long, long, int, String) formatDateRange} 1491427657d0bf7e69b831aa495828f67b45b69fd99Erik * @return a string containing the formatted date/time range. 1501427657d0bf7e69b831aa495828f67b45b69fd99Erik */ 1517b92da258a480284dcc15a518ea570072329a31dErik public static String formatDateRange( 1527b92da258a480284dcc15a518ea570072329a31dErik Context context, long startMillis, long endMillis, int flags) { 153a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik return mTZUtils.formatDateRange(context, startMillis, endMillis, flags); 154a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik } 155a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik 156a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik public static String getSharedPreference(Context context, String key, String defaultValue) { 157a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 158a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik return prefs.getString(key, defaultValue); 1591427657d0bf7e69b831aa495828f67b45b69fd99Erik } 1601427657d0bf7e69b831aa495828f67b45b69fd99Erik 161d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan public static int getSharedPreference(Context context, String key, int defaultValue) { 1624b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 163d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan return prefs.getInt(key, defaultValue); 164d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan } 165d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan 166ca4786769151f97069980443ce43d9c4f867ac5bErik public static boolean getSharedPreference(Context context, String key, boolean defaultValue) { 167ca4786769151f97069980443ce43d9c4f867ac5bErik SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 168ca4786769151f97069980443ce43d9c4f867ac5bErik return prefs.getBoolean(key, defaultValue); 169ca4786769151f97069980443ce43d9c4f867ac5bErik } 170ca4786769151f97069980443ce43d9c4f867ac5bErik 171f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang /** 172f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang * Asynchronously sets the preference with the given key to the given value 173f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang * 174f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang * @param context the context to use to get preferences from 175f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang * @param key the key of the preference to set 176f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang * @param value the value to set 177f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang */ 178fbce65e53c7a111955f638db5bf8bee35381e5b7Erik public static void setSharedPreference(Context context, String key, String value) { 1794b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 18024fac46d6b87ce21d5e6a4b1c0fdcaa83d408997Brad Fitzpatrick prefs.edit().putString(key, value).apply(); 18145efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan } 18245efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan 183ca4786769151f97069980443ce43d9c4f867ac5bErik protected static void tardis() { 184ca4786769151f97069980443ce43d9c4f867ac5bErik mTardis = System.currentTimeMillis(); 185ca4786769151f97069980443ce43d9c4f867ac5bErik } 186ca4786769151f97069980443ce43d9c4f867ac5bErik 187ca4786769151f97069980443ce43d9c4f867ac5bErik protected static long getTardis() { 188ca4786769151f97069980443ce43d9c4f867ac5bErik return mTardis; 189ca4786769151f97069980443ce43d9c4f867ac5bErik } 190ca4786769151f97069980443ce43d9c4f867ac5bErik 1913dc5e908a825b879978ba523d9099dc2255da9a5Erik static void setSharedPreference(Context context, String key, boolean value) { 1924b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 1933dc5e908a825b879978ba523d9099dc2255da9a5Erik SharedPreferences.Editor editor = prefs.edit(); 1943dc5e908a825b879978ba523d9099dc2255da9a5Erik editor.putBoolean(key, value); 195275232dae58bb24e3360a779ada9d24601a99bcfErik editor.apply(); 1963dc5e908a825b879978ba523d9099dc2255da9a5Erik } 1973dc5e908a825b879978ba523d9099dc2255da9a5Erik 198d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan static void setSharedPreference(Context context, String key, int value) { 199d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 200d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan SharedPreferences.Editor editor = prefs.edit(); 201d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan editor.putInt(key, value); 202d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan editor.apply(); 203d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 204d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 205d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan /** 206d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan * Save default agenda/day/week/month view for next time 207d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan * 208d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan * @param context 209d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan * @param viewId {@link CalendarController.ViewType} 210d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan */ 211e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan static void setDefaultView(Context context, int viewId) { 2124b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 213e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan SharedPreferences.Editor editor = prefs.edit(); 214f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang 215b60218a31d948ea0a549daf6464063d20b48421fMichael Chan boolean validDetailView = false; 216b60218a31d948ea0a549daf6464063d20b48421fMichael Chan if (mAllowWeekForDetailView && viewId == CalendarController.ViewType.WEEK) { 217b60218a31d948ea0a549daf6464063d20b48421fMichael Chan validDetailView = true; 218b60218a31d948ea0a549daf6464063d20b48421fMichael Chan } else { 219b60218a31d948ea0a549daf6464063d20b48421fMichael Chan validDetailView = viewId == CalendarController.ViewType.AGENDA 220b60218a31d948ea0a549daf6464063d20b48421fMichael Chan || viewId == CalendarController.ViewType.DAY; 221b60218a31d948ea0a549daf6464063d20b48421fMichael Chan } 222b60218a31d948ea0a549daf6464063d20b48421fMichael Chan 223b60218a31d948ea0a549daf6464063d20b48421fMichael Chan if (validDetailView) { 224b60218a31d948ea0a549daf6464063d20b48421fMichael Chan // Record the detail start view 2254b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa editor.putInt(GeneralPreferences.KEY_DETAILED_VIEW, viewId); 226e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan } 227e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan 228e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan // Record the (new) start view 2294b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa editor.putInt(GeneralPreferences.KEY_START_VIEW, viewId); 23024fac46d6b87ce21d5e6a4b1c0fdcaa83d408997Brad Fitzpatrick editor.apply(); 231e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan } 232e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan 233a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik public static MatrixCursor matrixCursorFromCursor(Cursor cursor) { 234a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames()); 235a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik int numColumns = cursor.getColumnCount(); 236a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik String data[] = new String[numColumns]; 237a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik cursor.moveToPosition(-1); 238a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik while (cursor.moveToNext()) { 239a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik for (int i = 0; i < numColumns; i++) { 240a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik data[i] = cursor.getString(i); 241a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 242a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik newCursor.addRow(data); 243a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 244a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return newCursor; 245a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 246a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 247a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik /** 248a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik * Compares two cursors to see if they contain the same data. 249a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik * 2507b92da258a480284dcc15a518ea570072329a31dErik * @return Returns true of the cursors contain the same data and are not 2517b92da258a480284dcc15a518ea570072329a31dErik * null, false otherwise 252a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik */ 253a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik public static boolean compareCursors(Cursor c1, Cursor c2) { 2547b92da258a480284dcc15a518ea570072329a31dErik if (c1 == null || c2 == null) { 255a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return false; 256a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 257a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 258a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik int numColumns = c1.getColumnCount(); 259a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik if (numColumns != c2.getColumnCount()) { 260a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return false; 261a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 262a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 263a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik if (c1.getCount() != c2.getCount()) { 264a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return false; 265a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 266a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 267a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik c1.moveToPosition(-1); 268a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik c2.moveToPosition(-1); 2697b92da258a480284dcc15a518ea570072329a31dErik while (c1.moveToNext() && c2.moveToNext()) { 2707b92da258a480284dcc15a518ea570072329a31dErik for (int i = 0; i < numColumns; i++) { 2717b92da258a480284dcc15a518ea570072329a31dErik if (!TextUtils.equals(c1.getString(i), c2.getString(i))) { 272a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return false; 273a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 274a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 275a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 276a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 277a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return true; 278a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 279a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * If the given intent specifies a time (in milliseconds since the epoch), 282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * then that time is returned. Otherwise, the current time is returned. 283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public static final long timeFromIntentInMillis(Intent intent) { 2857b92da258a480284dcc15a518ea570072329a31dErik // If the time was specified, then use that. Otherwise, use the current 2867b92da258a480284dcc15a518ea570072329a31dErik // time. 2871ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik Uri data = intent.getData(); 288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = intent.getLongExtra(EVENT_BEGIN_TIME, -1); 2891ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik if (millis == -1 && data != null && data.isHierarchical()) { 2901ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik List<String> path = data.getPathSegments(); 2917b92da258a480284dcc15a518ea570072329a31dErik if (path.size() == 2 && path.get(0).equals("time")) { 2921ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik try { 2931ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik millis = Long.valueOf(data.getLastPathSegment()); 2941ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik } catch (NumberFormatException e) { 2957b92da258a480284dcc15a518ea570072329a31dErik Log.i("Calendar", "timeFromIntentInMillis: Data existed but no valid time " 2967b92da258a480284dcc15a518ea570072329a31dErik + "found. Using current time."); 2971ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik } 2981ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik } 2991ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik } 30076727b7a9cf780f200414548b9d454bf9a701e3eErik if (millis <= 0) { 301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project millis = System.currentTimeMillis(); 302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return millis; 304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 3077b92da258a480284dcc15a518ea570072329a31dErik * Formats the given Time object so that it gives the month and year (for 3087b92da258a480284dcc15a518ea570072329a31dErik * example, "September 2007"). 309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param time the time to format 311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @return the string containing the weekday and the date 312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 313ad36a3c3cde7a2ec6d3a35d2529d46f03bd8d59dMichael Chan public static String formatMonthYear(Context context, Time time) { 314cfa204ba5c59eb6ebd4b54788ceb31010e4a37a0RoboErik int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_MONTH_DAY 315cfa204ba5c59eb6ebd4b54788ceb31010e4a37a0RoboErik | DateUtils.FORMAT_SHOW_YEAR; 316cfa204ba5c59eb6ebd4b54788ceb31010e4a37a0RoboErik long millis = time.toMillis(true); 317cfa204ba5c59eb6ebd4b54788ceb31010e4a37a0RoboErik return formatDateRange(context, millis, millis, flags); 318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 320146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 3214c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * Returns a list joined together by the provided delimiter, for example, 3224c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * ["a", "b", "c"] could be joined into "a,b,c" 3234c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * 3244c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * @param things the things to join together 3254c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * @param delim the delimiter to use 3264c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * @return a string contained the things joined together 3274c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang */ 3284c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang public static String join(List<?> things, String delim) { 3294c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang StringBuilder builder = new StringBuilder(); 3304c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang boolean first = true; 3314c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang for (Object thing : things) { 3324c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang if (first) { 3334c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang first = false; 3344c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang } else { 3354c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang builder.append(delim); 3364c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang } 3374c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang builder.append(thing.toString()); 3384c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang } 3394c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang return builder.toString(); 3404c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang } 3414c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang 3424c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang /** 343981874e61ecf29a96a77601a3172b2503b6537eeErik * Returns the week since {@link Time#EPOCH_JULIAN_DAY} (Jan 1, 1970) 344981874e61ecf29a96a77601a3172b2503b6537eeErik * adjusted for first day of week. 345981874e61ecf29a96a77601a3172b2503b6537eeErik * 346981874e61ecf29a96a77601a3172b2503b6537eeErik * This takes a julian day and the week start day and calculates which 347981874e61ecf29a96a77601a3172b2503b6537eeErik * week since {@link Time#EPOCH_JULIAN_DAY} that day occurs in, starting 348981874e61ecf29a96a77601a3172b2503b6537eeErik * at 0. *Do not* use this to compute the ISO week number for the year. 349981874e61ecf29a96a77601a3172b2503b6537eeErik * 350981874e61ecf29a96a77601a3172b2503b6537eeErik * @param julianDay The julian day to calculate the week number for 351981874e61ecf29a96a77601a3172b2503b6537eeErik * @param firstDayOfWeek Which week day is the first day of the week, 352981874e61ecf29a96a77601a3172b2503b6537eeErik * see {@link Time#SUNDAY} 353981874e61ecf29a96a77601a3172b2503b6537eeErik * @return Weeks since the epoch 354981874e61ecf29a96a77601a3172b2503b6537eeErik */ 355981874e61ecf29a96a77601a3172b2503b6537eeErik public static int getWeeksSinceEpochFromJulianDay(int julianDay, int firstDayOfWeek) { 356981874e61ecf29a96a77601a3172b2503b6537eeErik int diff = Time.THURSDAY - firstDayOfWeek; 357981874e61ecf29a96a77601a3172b2503b6537eeErik if (diff < 0) { 358981874e61ecf29a96a77601a3172b2503b6537eeErik diff += 7; 359981874e61ecf29a96a77601a3172b2503b6537eeErik } 360981874e61ecf29a96a77601a3172b2503b6537eeErik int refDay = Time.EPOCH_JULIAN_DAY - diff; 361981874e61ecf29a96a77601a3172b2503b6537eeErik return (julianDay - refDay) / 7; 362981874e61ecf29a96a77601a3172b2503b6537eeErik } 363981874e61ecf29a96a77601a3172b2503b6537eeErik 364981874e61ecf29a96a77601a3172b2503b6537eeErik /** 365981874e61ecf29a96a77601a3172b2503b6537eeErik * Takes a number of weeks since the epoch and calculates the Julian day of 366981874e61ecf29a96a77601a3172b2503b6537eeErik * the Monday for that week. 367981874e61ecf29a96a77601a3172b2503b6537eeErik * 368981874e61ecf29a96a77601a3172b2503b6537eeErik * This assumes that the week containing the {@link Time#EPOCH_JULIAN_DAY} 369981874e61ecf29a96a77601a3172b2503b6537eeErik * is considered week 0. It returns the Julian day for the Monday 370981874e61ecf29a96a77601a3172b2503b6537eeErik * {@code week} weeks after the Monday of the week containing the epoch. 371981874e61ecf29a96a77601a3172b2503b6537eeErik * 372981874e61ecf29a96a77601a3172b2503b6537eeErik * @param week Number of weeks since the epoch 373981874e61ecf29a96a77601a3172b2503b6537eeErik * @return The julian day for the Monday of the given week since the epoch 374981874e61ecf29a96a77601a3172b2503b6537eeErik */ 375981874e61ecf29a96a77601a3172b2503b6537eeErik public static int getJulianMondayFromWeeksSinceEpoch(int week) { 376981874e61ecf29a96a77601a3172b2503b6537eeErik return MONDAY_BEFORE_JULIAN_EPOCH + week * 7; 377981874e61ecf29a96a77601a3172b2503b6537eeErik } 378981874e61ecf29a96a77601a3172b2503b6537eeErik 379981874e61ecf29a96a77601a3172b2503b6537eeErik /** 38056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * Get first day of week as android.text.format.Time constant. 3817b92da258a480284dcc15a518ea570072329a31dErik * 38256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @return the first day of week in android.text.format.Time 38356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi */ 3848e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang public static int getFirstDayOfWeek(Context context) { 3854b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 3867b92da258a480284dcc15a518ea570072329a31dErik String pref = prefs.getString( 3877b92da258a480284dcc15a518ea570072329a31dErik GeneralPreferences.KEY_WEEK_START_DAY, GeneralPreferences.WEEK_START_DEFAULT); 3888e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang 3898e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang int startDay; 3904b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa if (GeneralPreferences.WEEK_START_DEFAULT.equals(pref)) { 3918e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang startDay = Calendar.getInstance().getFirstDayOfWeek(); 3928e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang } else { 3938e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang startDay = Integer.parseInt(pref); 3948e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang } 3958e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang 39656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi if (startDay == Calendar.SATURDAY) { 39756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi return Time.SATURDAY; 39856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } else if (startDay == Calendar.MONDAY) { 39956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi return Time.MONDAY; 40056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } else { 40156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi return Time.SUNDAY; 40256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } 40356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } 40456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi 40556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi /** 406d644b0df14ae6e204369b3454d16976fba32f15cDaisuke Miyakawa * @return true when week number should be shown. 407981874e61ecf29a96a77601a3172b2503b6537eeErik */ 408981874e61ecf29a96a77601a3172b2503b6537eeErik public static boolean getShowWeekNumber(Context context) { 409d644b0df14ae6e204369b3454d16976fba32f15cDaisuke Miyakawa final SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 410981874e61ecf29a96a77601a3172b2503b6537eeErik return prefs.getBoolean( 411981874e61ecf29a96a77601a3172b2503b6537eeErik GeneralPreferences.KEY_SHOW_WEEK_NUM, GeneralPreferences.DEFAULT_SHOW_WEEK_NUM); 412981874e61ecf29a96a77601a3172b2503b6537eeErik } 413981874e61ecf29a96a77601a3172b2503b6537eeErik 414981874e61ecf29a96a77601a3172b2503b6537eeErik /** 41540bcd101b212c9863c3110c05a487a7ae6ebc3caErik * @return true when declined events should be hidden. 41640bcd101b212c9863c3110c05a487a7ae6ebc3caErik */ 41740bcd101b212c9863c3110c05a487a7ae6ebc3caErik public static boolean getHideDeclinedEvents(Context context) { 41840bcd101b212c9863c3110c05a487a7ae6ebc3caErik final SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 41940bcd101b212c9863c3110c05a487a7ae6ebc3caErik return prefs.getBoolean(GeneralPreferences.KEY_HIDE_DECLINED, false); 42040bcd101b212c9863c3110c05a487a7ae6ebc3caErik } 42140bcd101b212c9863c3110c05a487a7ae6ebc3caErik 42291b01ed605e36fc5a7a924c226597a62c789b50dErik public static int getDaysPerWeek(Context context) { 42391b01ed605e36fc5a7a924c226597a62c789b50dErik final SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 42491b01ed605e36fc5a7a924c226597a62c789b50dErik return prefs.getInt(GeneralPreferences.KEY_DAYS_PER_WEEK, 7); 42591b01ed605e36fc5a7a924c226597a62c789b50dErik } 42691b01ed605e36fc5a7a924c226597a62c789b50dErik 42740bcd101b212c9863c3110c05a487a7ae6ebc3caErik /** 42856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * Determine whether the column position is Saturday or not. 4297b92da258a480284dcc15a518ea570072329a31dErik * 43056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @param column the column position 43156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @param firstDayOfWeek the first day of week in android.text.format.Time 43256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @return true if the column is Saturday position 43356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi */ 43456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi public static boolean isSaturday(int column, int firstDayOfWeek) { 43556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi return (firstDayOfWeek == Time.SUNDAY && column == 6) 4367b92da258a480284dcc15a518ea570072329a31dErik || (firstDayOfWeek == Time.MONDAY && column == 5) 4377b92da258a480284dcc15a518ea570072329a31dErik || (firstDayOfWeek == Time.SATURDAY && column == 0); 43856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } 43956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi 44056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi /** 44156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * Determine whether the column position is Sunday or not. 4427b92da258a480284dcc15a518ea570072329a31dErik * 44356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @param column the column position 44456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @param firstDayOfWeek the first day of week in android.text.format.Time 44556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @return true if the column is Sunday position 44656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi */ 44756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi public static boolean isSunday(int column, int firstDayOfWeek) { 44856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi return (firstDayOfWeek == Time.SUNDAY && column == 0) 4497b92da258a480284dcc15a518ea570072329a31dErik || (firstDayOfWeek == Time.MONDAY && column == 6) 4507b92da258a480284dcc15a518ea570072329a31dErik || (firstDayOfWeek == Time.SATURDAY && column == 1); 45156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } 452ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan 453ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan /** 4549da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik * Convert given UTC time into current local time. This assumes it is for an 4559da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik * allday event and will adjust the time to be on a midnight boundary. 4563ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang * 4573ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang * @param recycle Time object to recycle, otherwise null. 4583ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang * @param utcTime Time to convert, in UTC. 4599da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik * @param tz The time zone to convert this time to. 4603ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang */ 4619da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik public static long convertAlldayUtcToLocal(Time recycle, long utcTime, String tz) { 4623ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang if (recycle == null) { 4633ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang recycle = new Time(); 4643ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang } 4653ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang recycle.timezone = Time.TIMEZONE_UTC; 4663ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang recycle.set(utcTime); 4679da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik recycle.timezone = tz; 4689da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik return recycle.normalize(true); 4699da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik } 4709da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik 4719da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik public static long convertAlldayLocalToUTC(Time recycle, long localTime, String tz) { 4729da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik if (recycle == null) { 4739da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik recycle = new Time(); 4749da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik } 4759da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik recycle.timezone = tz; 4769da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik recycle.set(localTime); 4779da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik recycle.timezone = Time.TIMEZONE_UTC; 4783ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang return recycle.normalize(true); 4793ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang } 4803ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang 4813ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang /** 482ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan * Scan through a cursor of calendars and check if names are duplicated. 4837b92da258a480284dcc15a518ea570072329a31dErik * This travels a cursor containing calendar display names and fills in the 4847b92da258a480284dcc15a518ea570072329a31dErik * provided map with whether or not each name is repeated. 485ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan * 486ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan * @param isDuplicateName The map to put the duplicate check results in. 487ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan * @param cursor The query of calendars to check 488ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan * @param nameIndex The column of the query that contains the display name 489ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan */ 4907b92da258a480284dcc15a518ea570072329a31dErik public static void checkForDuplicateNames( 4917b92da258a480284dcc15a518ea570072329a31dErik Map<String, Boolean> isDuplicateName, Cursor cursor, int nameIndex) { 492ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan isDuplicateName.clear(); 493ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan cursor.moveToPosition(-1); 494ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan while (cursor.moveToNext()) { 495ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan String displayName = cursor.getString(nameIndex); 496ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan // Set it to true if we've seen this name before, false otherwise 497ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan if (displayName != null) { 498ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan isDuplicateName.put(displayName, isDuplicateName.containsKey(displayName)); 499ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan } 500ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan } 501ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan } 5029138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang 5039138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang /** 5049138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang * Null-safe object comparison 5057b92da258a480284dcc15a518ea570072329a31dErik * 5069138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang * @param s1 5079138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang * @param s2 5089138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang * @return 5099138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang */ 5109138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang public static boolean equals(Object o1, Object o2) { 5119138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang return o1 == null ? o2 == null : o1.equals(o2); 5129138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang } 513b60218a31d948ea0a549daf6464063d20b48421fMichael Chan 51463cd053150e00fde045b019dbe0f48b8a9ed3559Erik public static void setAllowWeekForDetailView(boolean allowWeekView) { 515b60218a31d948ea0a549daf6464063d20b48421fMichael Chan mAllowWeekForDetailView = allowWeekView; 516b60218a31d948ea0a549daf6464063d20b48421fMichael Chan } 51763cd053150e00fde045b019dbe0f48b8a9ed3559Erik 51863cd053150e00fde045b019dbe0f48b8a9ed3559Erik public static boolean getAllowWeekForDetailView() { 51963cd053150e00fde045b019dbe0f48b8a9ed3559Erik return mAllowWeekForDetailView; 52063cd053150e00fde045b019dbe0f48b8a9ed3559Erik } 5210b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson 5220b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson public static boolean isMultiPaneConfiguration (Context c) { 5230b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson return (c.getResources().getConfiguration().screenLayout & 5240b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson Configuration.SCREENLAYOUT_SIZE_XLARGE) != 0; 5250b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson } 526ff5c4345f794ec12b0a92f284434ddc1c88ff3a8Isaac Katzenelson 527ff5c4345f794ec12b0a92f284434ddc1c88ff3a8Isaac Katzenelson public static boolean getConfigBool(Context c, int key) { 528ff5c4345f794ec12b0a92f284434ddc1c88ff3a8Isaac Katzenelson return c.getResources().getBoolean(key); 529ff5c4345f794ec12b0a92f284434ddc1c88ff3a8Isaac Katzenelson } 53082400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 53182400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 53282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson // Helper class for createBusyBitSegments function 53382400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 53482400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson public static class BusyBitsSegment { 53582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson public int start, end; 53682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 53782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson BusyBitsSegment(int s, int e) { 53882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson start = s; 53982400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson end = e; 54082400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 54182400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 54282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson @Override 54382400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson public int hashCode() { 54482400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson final int prime = 31; 54582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson int result = 1; 54682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson result = prime * result + end; 54782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson result = prime * result + start; 54882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson return result; 54982400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 55082400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 55182400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson @Override 55282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson public boolean equals(Object obj) { 55382400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson if (this == obj) { 55482400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson return true; 55582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 55682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson if (obj == null) { 55782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson return false; 55882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 55982400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson if (getClass() != obj.getClass()) { 56082400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson return false; 56182400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 56282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson BusyBitsSegment other = (BusyBitsSegment) obj; 56382400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson if (end != other.end) { 56482400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson return false; 56582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 56682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson if (start != other.start) { 56782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson return false; 56882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 56982400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson return true; 57082400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 57182400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 57282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 57382400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson // Converts a list of events to a list of busy segments to draw 57482400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson // Assumes list is ordered according to start date 57582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 57682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson public static ArrayList<BusyBitsSegment> createBusyBitSegments(int pStart, int pEnd, 57782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson int startTime, int endTime, 57882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson ArrayList<Event> events) { 57982400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 58082400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson if (events == null || events.size() == 0 || pStart >= pEnd || startTime >= endTime) 58182400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson return null; 58282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 58382400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson ArrayList<BusyBitsSegment> segments = new ArrayList<BusyBitsSegment>(); 58482400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson int start = -1; 58582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson int end = -1; 58682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson int timeFrame = endTime - startTime; 58782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson int pSize = pEnd - pStart; 58882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 58982400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson // Iterate on events and create segments 59082400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson Iterator<Event> iter = events.iterator(); 59182400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson while (iter.hasNext()) { 59282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson Event event = iter.next(); 59382400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 59482400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson int eStart = event.startTime; 59582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson int eEnd = event.endTime; 59682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 59782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson // skip all day events, events that are not in the time frame and 59882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson // events that are zero length 59982400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson if (event.allDay || eStart >= endTime || eEnd <= startTime || eStart == eEnd) { 60082400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson continue; 60182400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 60282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 60382400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson if (eStart < startTime) { 60482400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson eStart = startTime; 60582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 60682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson if (eEnd > endTime) { 60782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson eEnd = endTime; 60882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 60982400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 61082400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson // first event , just take the values as the initial segment size 61182400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson if (start == -1 && end == -1) { 61282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson start = eStart; 61382400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson end = eEnd; 61482400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson continue; 61582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 61682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 61782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson // combine event with current segment 61882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson if (eStart <= end) { 61982400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson if (eEnd > end) { 62082400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson end = eEnd; 62182400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 62282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } else { 62382400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson // Push current segment to segment list and create a new segment 62482400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson BusyBitsSegment s = new BusyBitsSegment( 62582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson (start - startTime) * pSize / timeFrame + pStart, 62682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson (end - startTime) * pSize / timeFrame + pStart); 62782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson segments.add(s); 62882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson start = eStart; 62982400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson end = eEnd; 63082400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 63182400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 63282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 63382400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson if (start != end) { 63482400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson BusyBitsSegment s = new BusyBitsSegment( 63582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson (start - startTime) * pSize / timeFrame + pStart, 63682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson (end - startTime) * pSize / timeFrame + pStart); 63782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson segments.add(s); 63882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 63982400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson return segments; 64082400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 641146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project} 642