am 27d4616f: am b8f69516: Merge "Fix support for birthday on February 29th with year omitted" into jb-mr1-dev
* commit '27d4616f291e323dc1a20ebec935f2ac64de414e':
Fix support for birthday on February 29th with year omitted
diff --git a/src/com/android/contacts/datepicker/DatePicker.java b/src/com/android/contacts/datepicker/DatePicker.java
index ef91c95..39bbd8d 100644
--- a/src/com/android/contacts/datepicker/DatePicker.java
+++ b/src/com/android/contacts/datepicker/DatePicker.java
@@ -54,6 +54,8 @@
*/
@Widget
public class DatePicker extends FrameLayout {
+ /** Magic year that represents "no year" */
+ public static int NO_YEAR = 0;
private static final int DEFAULT_START_YEAR = 1900;
private static final int DEFAULT_END_YEAR = 2100;
@@ -83,7 +85,7 @@
/**
* @param view The view associated with this listener.
- * @param year The year that was set.
+ * @param year The year that was set or {@link DatePicker#NO_YEAR} if no year was set
* @param monthOfYear The month that was set (0-11) for compatibility
* with {@link java.util.Calendar}.
* @param dayOfMonth The day of the month that was set.
@@ -279,7 +281,7 @@
public void updateDate(int year, int monthOfYear, int dayOfMonth) {
if (mYear != year || mMonth != monthOfYear || mDay != dayOfMonth) {
- mYear = (mYearOptional && year == 0) ? getCurrentYear() : year;
+ mYear = (mYearOptional && year == NO_YEAR) ? getCurrentYear() : year;
mMonth = monthOfYear;
mDay = dayOfMonth;
updateSpinners();
@@ -413,7 +415,7 @@
/**
* Initialize the state.
- * @param year The initial year or 0 if no year has been specified
+ * @param year The initial year or {@link #NO_YEAR} if no year has been specified
* @param monthOfYear The initial month.
* @param dayOfMonth The initial day of the month.
* @param yearOptional True if the user can toggle the year
@@ -421,11 +423,11 @@
*/
public void init(int year, int monthOfYear, int dayOfMonth, boolean yearOptional,
OnDateChangedListener onDateChangedListener) {
- mYear = (yearOptional && year == 0) ? getCurrentYear() : year;
+ mYear = (yearOptional && year == NO_YEAR) ? getCurrentYear() : year;
mMonth = monthOfYear;
mDay = dayOfMonth;
mYearOptional = yearOptional;
- mHasYear = yearOptional ? (year != 0) : true;
+ mHasYear = yearOptional ? (year != NO_YEAR) : true;
mOnDateChangedListener = onDateChangedListener;
updateSpinners();
}
@@ -454,7 +456,7 @@
}
public int getYear() {
- return (mYearOptional && !mHasYear) ? 0 : mYear;
+ return (mYearOptional && !mHasYear) ? NO_YEAR : mYear;
}
public boolean isYearOptional() {
@@ -482,7 +484,7 @@
private void notifyDateChanged() {
if (mOnDateChangedListener != null) {
- int year = (mYearOptional && !mHasYear) ? 0 : mYear;
+ int year = (mYearOptional && !mHasYear) ? NO_YEAR : mYear;
mOnDateChangedListener.onDateChanged(DatePicker.this, year, mMonth, mDay);
}
}
diff --git a/src/com/android/contacts/datepicker/DatePickerDialog.java b/src/com/android/contacts/datepicker/DatePickerDialog.java
index 9c7cee6..14ebd3b 100644
--- a/src/com/android/contacts/datepicker/DatePickerDialog.java
+++ b/src/com/android/contacts/datepicker/DatePickerDialog.java
@@ -47,6 +47,9 @@
public class DatePickerDialog extends AlertDialog implements OnClickListener,
OnDateChangedListener {
+ /** Magic year that represents "no year" */
+ public static int NO_YEAR = DatePicker.NO_YEAR;
+
private static final String YEAR = "year";
private static final String MONTH = "month";
private static final String DAY = "day";
@@ -54,7 +57,6 @@
private final DatePicker mDatePicker;
private final OnDateSetListener mCallBack;
- private final Calendar mCalendar;
private final DateFormat mTitleDateFormat;
private final DateFormat mTitleNoYearDateFormat;
@@ -68,7 +70,8 @@
public interface OnDateSetListener {
/**
* @param view The view associated with this listener.
- * @param year The year that was set or 0 if the user has not specified a year
+ * @param year The year that was set or {@link DatePickerDialog#NO_YEAR} if the user has
+ * not specified a year
* @param monthOfYear The month that was set (0-11) for compatibility
* with {@link java.util.Calendar}.
* @param dayOfMonth The day of the month that was set.
@@ -94,7 +97,8 @@
/**
* @param context The context the dialog is to run in.
* @param callBack How the parent is notified that the date is set.
- * @param year The initial year of the dialog or 0 if no year has been specified
+ * @param year The initial year of the dialog or {@link DatePickerDialog#NO_YEAR} if no year
+ * has been specified
* @param monthOfYear The initial month of the dialog.
* @param dayOfMonth The initial day of the dialog.
* @param yearOptional Whether the year can be toggled by the user
@@ -115,7 +119,8 @@
* @param context The context the dialog is to run in.
* @param theme the theme to apply to this dialog
* @param callBack How the parent is notified that the date is set.
- * @param year The initial year of the dialog or 0 if no year has been specified
+ * @param year The initial year of the dialog or {@link DatePickerDialog#NO_YEAR} if no year
+ * has been specified
* @param monthOfYear The initial month of the dialog.
* @param dayOfMonth The initial day of the dialog.
*/
@@ -132,7 +137,8 @@
* @param context The context the dialog is to run in.
* @param theme the theme to apply to this dialog
* @param callBack How the parent is notified that the date is set.
- * @param year The initial year of the dialog.
+ * @param year The initial year of the dialog or {@link DatePickerDialog#NO_YEAR} if no
+ * year has been specified.
* @param monthOfYear The initial month of the dialog.
* @param dayOfMonth The initial day of the dialog.
* @param yearOptional Whether the year can be toggled by the user
@@ -154,7 +160,6 @@
mTitleDateFormat = DateFormat.getDateInstance(DateFormat.FULL);
mTitleNoYearDateFormat = new SimpleDateFormat(
DateUtils.isMonthBeforeDay(getContext()) ? "MMMM dd" : "dd MMMM");
- mCalendar = Calendar.getInstance();
updateTitle(mInitialYear, mInitialMonth, mInitialDay);
setButton(BUTTON_POSITIVE, context.getText(com.android.internal.R.string.date_time_set),
@@ -205,12 +210,13 @@
}
private void updateTitle(int year, int month, int day) {
- mCalendar.set(Calendar.YEAR, year);
- mCalendar.set(Calendar.MONTH, month);
- mCalendar.set(Calendar.DAY_OF_MONTH, day);
+ final Calendar calendar = Calendar.getInstance();
+ calendar.set(Calendar.YEAR, year);
+ calendar.set(Calendar.MONTH, month);
+ calendar.set(Calendar.DAY_OF_MONTH, day);
final DateFormat dateFormat =
- year == 0 ? mTitleNoYearDateFormat : mTitleDateFormat;
- setTitle(dateFormat.format(mCalendar.getTime()));
+ year == NO_YEAR ? mTitleNoYearDateFormat : mTitleDateFormat;
+ setTitle(dateFormat.format(calendar.getTime()));
}
@Override
diff --git a/src/com/android/contacts/editor/EventFieldEditorView.java b/src/com/android/contacts/editor/EventFieldEditorView.java
index ca1bf64..77f2010 100644
--- a/src/com/android/contacts/editor/EventFieldEditorView.java
+++ b/src/com/android/contacts/editor/EventFieldEditorView.java
@@ -203,7 +203,7 @@
final int oldYear, oldMonth, oldDay;
if (TextUtils.isEmpty(oldValue)) {
- // Default to January first, 30 years ago
+ // Default to January first of this year
oldYear = defaultYear;
oldMonth = 0;
oldDay = 1;
@@ -221,13 +221,25 @@
oldMonth = calendar.get(Calendar.MONTH);
oldDay = calendar.get(Calendar.DAY_OF_MONTH);
} else {
- final Date date2 = kind.dateFormatWithoutYear.parse(oldValue, position);
- // Don't understand the date, lets not change it
- if (date2 == null) return null;
- calendar.setTime(date2);
- oldYear = isYearOptional ? 0 : defaultYear;
- oldMonth = calendar.get(Calendar.MONTH);
- oldDay = calendar.get(Calendar.DAY_OF_MONTH);
+ // Unfortunately, we need a one-off hack for February 29th, because
+ // the parse functions assume 1970, which wasn't a leap year
+ // Caveat here: This won't catch AccountTypes that allow omitting the year but
+ // require a time of the day. But as we don't have any of those at the moment,
+ // this shouldn't be an issue
+ if (DateUtils.NO_YEAR_DATE_FEB29TH.equals(oldValue)) {
+ oldYear = isYearOptional ? DatePickerDialog.NO_YEAR : defaultYear;
+ oldMonth = Calendar.FEBRUARY;
+ oldDay = 29;
+ } else {
+ final Date date2 = kind.dateFormatWithoutYear.parse(oldValue, position);
+ // Don't understand the date? Let's not show any dialog
+ if (date2 == null) return null;
+
+ calendar.setTime(date2);
+ oldYear = isYearOptional ? DatePickerDialog.NO_YEAR : defaultYear;
+ oldMonth = calendar.get(Calendar.MONTH);
+ oldDay = calendar.get(Calendar.DAY_OF_MONTH);
+ }
}
}
final OnDateSetListener callBack = new OnDateSetListener() {
@@ -241,8 +253,8 @@
// The format string will ignore that year.
// For formats other than Exchange, the time of the day is ignored
outCalendar.clear();
- outCalendar.set(year == 0 ? 2000 : year, monthOfYear, dayOfMonth,
- DEFAULT_HOUR, 0, 0);
+ outCalendar.set(year == DatePickerDialog.NO_YEAR ? 2000 : year, monthOfYear,
+ dayOfMonth, DEFAULT_HOUR, 0, 0);
final String resultString;
if (year == 0) {
diff --git a/src/com/android/contacts/util/DateUtils.java b/src/com/android/contacts/util/DateUtils.java
index d0bb68f..89127c9 100644
--- a/src/com/android/contacts/util/DateUtils.java
+++ b/src/com/android/contacts/util/DateUtils.java
@@ -21,6 +21,7 @@
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
+import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
@@ -34,6 +35,11 @@
// All the SimpleDateFormats in this class use the UTC timezone
public static final SimpleDateFormat NO_YEAR_DATE_FORMAT =
new SimpleDateFormat("--MM-dd", Locale.US);
+ /**
+ * When parsing a date without a year, the system assumes 1970, which wasn't a leap-year.
+ * Let's add a one-off hack for that day of the year
+ */
+ public static final String NO_YEAR_DATE_FEB29TH = "--02-29";
public static final SimpleDateFormat FULL_DATE_FORMAT =
new SimpleDateFormat("yyyy-MM-dd", Locale.US);
public static final SimpleDateFormat DATE_AND_TIME_FORMAT =
@@ -88,6 +94,14 @@
return null;
}
+ private static final Date getUtcDate(int year, int month, int dayOfMonth) {
+ final Calendar calendar = Calendar.getInstance(UTC_TIMEZONE, Locale.US);
+ calendar.set(Calendar.YEAR, year);
+ calendar.set(Calendar.MONTH, month);
+ calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
+ return calendar.getTime();
+ }
+
/**
* Parses the supplied string to see if it looks like a date. If so,
* returns the same date in a cleaned-up format for the user. Otherwise, returns
@@ -105,13 +119,21 @@
ParsePosition parsePosition = new ParsePosition(0);
+ final boolean noYearParsed;
Date date;
- synchronized (NO_YEAR_DATE_FORMAT) {
- date = NO_YEAR_DATE_FORMAT.parse(string, parsePosition);
+ // Unfortunately, we can't parse Feb 29th correctly, so let's handle this day seperately
+ if (NO_YEAR_DATE_FEB29TH.equals(string)) {
+ date = getUtcDate(0, Calendar.FEBRUARY, 29);
+ noYearParsed = true;
+ } else {
+ synchronized (NO_YEAR_DATE_FORMAT) {
+ date = NO_YEAR_DATE_FORMAT.parse(string, parsePosition);
+ }
+ noYearParsed = parsePosition.getIndex() == string.length();
}
- if (parsePosition.getIndex() == string.length()) {
+ if (noYearParsed) {
java.text.DateFormat outFormat = isMonthBeforeDay(context)
? FORMAT_WITHOUT_YEAR_MONTH_FIRST
: FORMAT_WITHOUT_YEAR_DAY_FIRST;