DatePicker.java
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package androidx.leanback.widget.picker;
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import androidx.annotation.RestrictTo;
import androidx.leanback.R;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
/**
* {@link DatePicker} is a directly subclass of {@link Picker}.
* This class is a widget for selecting a date. The date can be selected by a
* year, month, and day Columns. The "minDate" and "maxDate" from which dates to be selected
* can be customized. The columns can be customized by attribute "datePickerFormat" or
* {@link #setDatePickerFormat(String)}.
*
* @attr ref R.styleable#lbDatePicker_android_maxDate
* @attr ref R.styleable#lbDatePicker_android_minDate
* @attr ref R.styleable#lbDatePicker_datePickerFormat
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
public class DatePicker extends Picker {
static final String LOG_TAG = "DatePicker";
private String mDatePickerFormat;
PickerColumn mMonthColumn;
PickerColumn mDayColumn;
PickerColumn mYearColumn;
int mColMonthIndex;
int mColDayIndex;
int mColYearIndex;
final static String DATE_FORMAT = "MM/dd/yyyy";
final DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
PickerUtility.DateConstant mConstant;
Calendar mMinDate;
Calendar mMaxDate;
Calendar mCurrentDate;
Calendar mTempDate;
public DatePicker(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DatePicker(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
updateCurrentLocale();
final TypedArray attributesArray = context.obtainStyledAttributes(attrs,
R.styleable.lbDatePicker);
String minDate = attributesArray.getString(R.styleable.lbDatePicker_android_minDate);
String maxDate = attributesArray.getString(R.styleable.lbDatePicker_android_maxDate);
mTempDate.clear();
if (!TextUtils.isEmpty(minDate)) {
if (!parseDate(minDate, mTempDate)) {
mTempDate.set(1900, 0, 1);
}
} else {
mTempDate.set(1900, 0, 1);
}
mMinDate.setTimeInMillis(mTempDate.getTimeInMillis());
mTempDate.clear();
if (!TextUtils.isEmpty(maxDate)) {
if (!parseDate(maxDate, mTempDate)) {
mTempDate.set(2100, 0, 1);
}
} else {
mTempDate.set(2100, 0, 1);
}
mMaxDate.setTimeInMillis(mTempDate.getTimeInMillis());
String datePickerFormat = attributesArray
.getString(R.styleable.lbDatePicker_datePickerFormat);
if (TextUtils.isEmpty(datePickerFormat)) {
datePickerFormat = new String(
android.text.format.DateFormat.getDateFormatOrder(context));
}
setDatePickerFormat(datePickerFormat);
}
private boolean parseDate(String date, Calendar outDate) {
try {
outDate.setTime(mDateFormat.parse(date));
return true;
} catch (ParseException e) {
Log.w(LOG_TAG, "Date: " + date + " not in format: " + DATE_FORMAT);
return false;
}
}
/**
* Returns the best localized representation of the date for the given date format and the
* current locale.
*
* @param datePickerFormat The date format skeleton (e.g. "dMy") used to gather the
* appropriate representation of the date in the current locale.
*
* @return The best localized representation of the date for the given date format
*/
String getBestYearMonthDayPattern(String datePickerFormat) {
final String yearPattern;
if (PickerUtility.SUPPORTS_BEST_DATE_TIME_PATTERN) {
yearPattern = android.text.format.DateFormat.getBestDateTimePattern(mConstant.locale,
datePickerFormat);
} else {
final java.text.DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(
getContext());
if (dateFormat instanceof SimpleDateFormat) {
yearPattern = ((SimpleDateFormat) dateFormat).toLocalizedPattern();
} else {
yearPattern = DATE_FORMAT;
}
}
return TextUtils.isEmpty(yearPattern) ? DATE_FORMAT : yearPattern;
}
/**
* Extracts the separators used to separate date fields (including before the first and after
* the last date field). The separators can vary based on the individual locale date format,
* defined in the Unicode CLDR and cannot be supposed to be "/".
*
* See http://unicode.org/cldr/trac/browser/trunk/common/main
*
* For example, for Croatian in dMy format, the best localized representation is "d. M. y". This
* method returns {"", ".", ".", "."}, where the first separator indicates nothing needs to be
* displayed to the left of the day field, "." needs to be displayed tos the right of the day
* field, and so forth.
*
* @return The ArrayList of separators to populate between the actual date fields in the
* DatePicker.
*/
List<CharSequence> extractSeparators() {
// Obtain the time format string per the current locale (e.g. h:mm a)
String hmaPattern = getBestYearMonthDayPattern(mDatePickerFormat);
List<CharSequence> separators = new ArrayList<>();
StringBuilder sb = new StringBuilder();
char lastChar = 'eb3b9ed0-f11d-0137-cfb9-0ebaa35b92c0';
// See http://www.unicode.org/reports/tr35/tr35-dates.html for date formats
final char[] dateFormats = {'Y', 'y', 'M', 'm', 'D', 'd'};
boolean processingQuote = false;
for (int i = 0; i < hmaPattern.length(); i++) {
char c = hmaPattern.charAt(i);
if (c == ' ') {
continue;
}
if (c == '