165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/*
265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Copyright (C) 2014 The Android Open Source Project
365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Licensed under the Apache License, Version 2.0 (the "License");
565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * you may not use this file except in compliance with the License.
665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * You may obtain a copy of the License at
765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *      http://www.apache.org/licenses/LICENSE-2.0
965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
1065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Unless required by applicable law or agreed to in writing, software
1165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * distributed under the License is distributed on an "AS IS" BASIS,
1265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * See the License for the specific language governing permissions and
1465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * limitations under the License.
1565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
1665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepackage com.android.tv.settings.widget.picker;
1865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Bundle;
2065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.View;
2165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
2265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.ArrayList;
2365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.Calendar;
2465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.Date;
2565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.GregorianCalendar;
2665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.widget.TextView;
2765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
2865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepublic class DatePicker extends Picker {
2965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
3065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String EXTRA_START_YEAR = "start_year";
3165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String EXTRA_YEAR_RANGE = "year_range";
3265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String EXTRA_DEFAULT_TO_CURRENT = "default_to_current";
3365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String EXTRA_FORMAT = "date_format";
3465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final int DEFAULT_YEAR_RANGE = 24;
3565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final int DEFAULT_START_YEAR = Calendar.getInstance().get(Calendar.YEAR);
3665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private String[] mYears;
3765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int mStartYear;
3865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int mYearRange;
3965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private String[] mDayString = null;
4065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int mColMonthIndex = 0;
4165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int mColDayIndex = 1;
4265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int mColYearIndex = 2;
4365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private boolean mPendingDate = false;
4565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int mInitYear;
4665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int mInitMonth;
4765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int mInitDay;
4865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int mSelectedYear = DEFAULT_START_YEAR;
5165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private String mSelectedMonth;
5265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static DatePicker newInstance() {
5465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return newInstance("");
5565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
5665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
5865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Creates a new instance of DatePicker
5965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     *
6065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param format         String containing a permutation of Y, M and D, indicating the order
6165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     *                       of the fields Year, Month and Day to be displayed in the DatePicker.
6265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
6365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static DatePicker newInstance(String format) {
6465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return newInstance(format, DEFAULT_START_YEAR);
6565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
6665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
6865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Creates a new instance of DatePicker
6965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     *
7065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param format         String containing a permutation of Y, M and D, indicating the order
7165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     *                       of the fields Year, Month and Day to be displayed in the DatePicker.
7265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param startYear      The lowest number to be displayed in the Year selector.
7365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
7465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static DatePicker newInstance(String format, int startYear) {
7565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return newInstance(format, startYear, DEFAULT_YEAR_RANGE, true);
7665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
7765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
7865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
7965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Creates a new instance of DatePicker
8065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     *
8165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param format         String containing a permutation of Y, M and D, indicating the order
8265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     *                       of the fields Year, Month and Day to be displayed in the DatePicker.
8365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param startYear      The lowest number to be displayed in the Year selector.
8465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param yearRange      Number of entries to be displayed in the Year selector.
8565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param startOnToday   Indicates if the date should be set to the current date by default.
8665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
8765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static DatePicker newInstance(String format, int startYear, int yearRange,
8865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            boolean startOnToday) {
8965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        DatePicker datePicker = new DatePicker();
9065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (startYear <= 0) {
9165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            throw new IllegalArgumentException("The start year must be > 0. Got " + startYear);
9265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
9365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (yearRange <= 0) {
9465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            throw new IllegalArgumentException("The year range must be > 0. Got " + yearRange);
9565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
9665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Bundle args = new Bundle();
9765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        args.putString(EXTRA_FORMAT, format);
9865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        args.putInt(EXTRA_START_YEAR, startYear);
9965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        args.putInt(EXTRA_YEAR_RANGE, yearRange);
10065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        args.putBoolean(EXTRA_DEFAULT_TO_CURRENT, startOnToday);
10165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        datePicker.setArguments(args);
10265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return datePicker;
10365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
10465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
10565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private void initYearsArray(int startYear, int yearRange) {
10665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mYears = new String[yearRange];
10765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        for (int i = 0; i < yearRange; i++) {
10865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mYears[i] = String.valueOf(startYear + i);
10965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
11065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
11165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
11265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
11365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void onCreate(Bundle savedInstanceState) {
11465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        super.onCreate(savedInstanceState);
11565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mStartYear = getArguments().getInt(EXTRA_START_YEAR, DEFAULT_START_YEAR);
11665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mYearRange = getArguments().getInt(EXTRA_YEAR_RANGE, DEFAULT_YEAR_RANGE);
11765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        boolean startOnToday = getArguments().getBoolean(EXTRA_DEFAULT_TO_CURRENT, false);
11865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mSelectedMonth = mConstant.months[0];
11965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        initYearsArray(mStartYear, mYearRange);
12065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
12165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mDayString = mConstant.days30;
12265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
12365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        String format = getArguments().getString(EXTRA_FORMAT);
12465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (format != null && !format.isEmpty()) {
12565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            format = format.toUpperCase();
12665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
12765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            int yIndex = format.indexOf('Y');
12865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            int mIndex = format.indexOf('M');
12965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            int dIndex = format.indexOf('D');
13065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (yIndex < 0 || mIndex < 0 || dIndex < 0 || yIndex > 2 || mIndex > 2 || dIndex > 2) {
13165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                // Badly formatted input. Use default order.
13265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mColMonthIndex = 0;
13365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mColDayIndex = 1;
13465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mColYearIndex = 2;
13565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else {
13665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mColMonthIndex = mIndex;
13765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mColDayIndex = dIndex;
13865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mColYearIndex = yIndex;
13965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
14065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
14165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
14265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (startOnToday) {
14365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mPendingDate = true;
14465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Calendar cal = Calendar.getInstance();
14565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mInitYear = cal.get(Calendar.YEAR);
14665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mInitMonth = cal.get(Calendar.MONTH);
14765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mInitDay = cal.get(Calendar.DATE);
14865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
14965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
15065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
15165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
15265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void onResume() {
15365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mPendingDate) {
15465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mPendingDate = false;
15565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            setDate(mInitYear, mInitMonth, mInitDay);
15665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
15765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        super.onResume();
15865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
15965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
16065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
16165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected ArrayList<PickerColumn> getColumns() {
16265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        ArrayList<PickerColumn> ret = new ArrayList<PickerColumn>();
16365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // TODO orders of these columns might need to be localized
16465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        PickerColumn months = new PickerColumn(mConstant.months);
16565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        PickerColumn days = new PickerColumn(mDayString);
16665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        PickerColumn years = new PickerColumn(mYears);
16765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
16865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        for (int i = 0; i < 3; i++) {
16965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (i == mColYearIndex) {
17065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                ret.add(years);
17165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else if (i == mColMonthIndex) {
17265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                ret.add(months);
17365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else if (i == mColDayIndex) {
17465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                ret.add(days);
17565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
17665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
17765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
17865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return ret;
17965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
18065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
18165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
18265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected String getSeparator() {
18365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mConstant.dateSeparator;
18465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
18565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
18665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected boolean setDate(int year, int month, int day) {
18765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        boolean isLeapYear = false;
18865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
18965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (year < mStartYear || year > (mStartYear + mYearRange)) {
19065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return false;
19165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
19265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
19365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // Test to see if this is a valid date
19465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        try {
19565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            GregorianCalendar cal = new GregorianCalendar(year, month, day);
19665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            cal.setLenient(false);
19765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Date test = cal.getTime();
19865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } catch (IllegalArgumentException e) {
19965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return false;
20065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
20165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
20265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mSelectedYear = year;
20365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mSelectedMonth = mConstant.months[month];
20465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
20565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        updateSelection(mColYearIndex, year - mStartYear);
20665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        updateSelection(mColMonthIndex, month);
20765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
20865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        String[] dayString = null;
20965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // This is according to http://en.wikipedia.org/wiki/Leap_year#Algorithm
21065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (year % 400 == 0) {
21165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            isLeapYear = true;
21265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else if (year % 100 == 0) {
21365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            isLeapYear = false;
21465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else if (year % 4 == 0) {
21565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            isLeapYear = true;
21665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
21765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
21865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (month == 1) {
21965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (isLeapYear) {
22065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                dayString = mConstant.days29;
22165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else {
22265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                dayString = mConstant.days28;
22365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
22465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else if ((month == 3) || (month == 5) || (month == 8) || (month == 10)) {
22565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            dayString = mConstant.days30;
22665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else {
22765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            dayString = mConstant.days31;
22865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
22965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
23065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mDayString != dayString) {
23165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mDayString = dayString;
23265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            updateAdapter(mColDayIndex, new PickerColumn(mDayString));
23365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
23465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
23565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        updateSelection(mColDayIndex, day - 1);
23665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return true;
23765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
23865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
23965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
24065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void onScroll(View v) {
24165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        int column = (Integer) v.getTag();
24265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        String text = ((TextView) v).getText().toString();
24365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (column == mColMonthIndex) {
24465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mSelectedMonth = text;
24565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else if (column == mColYearIndex) {
24665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mSelectedYear = Integer.parseInt(text);
24765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else {
24865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return;
24965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
25065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
25165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        String[] dayString = null;
25265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
25365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        boolean isLeapYear = false;
25465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // This is according to http://en.wikipedia.org/wiki/Leap_year#Algorithm
25565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mSelectedYear % 400 == 0) {
25665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            isLeapYear = true;
25765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else if (mSelectedYear % 100 == 0) {
25865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            isLeapYear = false;
25965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else if (mSelectedYear % 4 == 0) {
26065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            isLeapYear = true;
26165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
26265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mSelectedMonth.equals(mConstant.months[1])) {
26365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (isLeapYear) {
26465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                dayString = mConstant.days29;
26565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else {
26665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                dayString = mConstant.days28;
26765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
26865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else if (mSelectedMonth.equals(mConstant.months[3])
26965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                || mSelectedMonth.equals(mConstant.months[5])
27065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                || mSelectedMonth.equals(mConstant.months[8])
27165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                || mSelectedMonth.equals(mConstant.months[10])) {
27265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            dayString = mConstant.days30;
27365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else {
27465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            dayString = mConstant.days31;
27565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
27665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (!mDayString.equals(dayString)) {
27765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mDayString = dayString;
27865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            updateAdapter(mColDayIndex, new PickerColumn(mDayString));
27965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
28065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
28165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane}
282