1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file.
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccipackage org.chromium.ui.picker;
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport android.content.Context;
8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport org.chromium.ui.R;
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import java.util.Calendar;
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)import java.util.TimeZone;
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// This class is heavily based on android.widget.DatePicker.
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochpublic class WeekPicker extends TwoFieldDatePicker {
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    public WeekPicker(Context context, double minValue, double maxValue) {
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        super(context, minValue, maxValue);
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        getPositionInYearSpinner().setContentDescription(
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                getResources().getString(R.string.accessibility_date_picker_week));
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // initialize to current date
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        cal.setFirstDayOfWeek(Calendar.MONDAY);
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        cal.setMinimalDaysInFirstWeek(4);
27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        cal.setTimeInMillis(System.currentTimeMillis());
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        init(getISOWeekYearForDate(cal), getWeekForDate(cal), null);
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    /**
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)     * Creates a date object from the |year| and |week|.
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)     */
34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    public static Calendar createDateFromWeek(int year, int week) {
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        Calendar date = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        date.clear();
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        date.setFirstDayOfWeek(Calendar.MONDAY);
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        date.setMinimalDaysInFirstWeek(4);
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        date.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        date.set(Calendar.YEAR, year);
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        date.set(Calendar.WEEK_OF_YEAR, week);
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return date;
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    /**
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)     * Creates a date object from the |value| which is milliseconds since epoch.
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)     */
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    public static Calendar createDateFromValue(double value) {
49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        Calendar date = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        date.clear();
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        date.setFirstDayOfWeek(Calendar.MONDAY);
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        date.setMinimalDaysInFirstWeek(4);
53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        date.setTimeInMillis((long) value);
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return date;
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    @Override
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    protected Calendar getDateForValue(double value) {
59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        return WeekPicker.createDateFromValue(value);
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    public static int getISOWeekYearForDate(Calendar date) {
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        int year = date.get(Calendar.YEAR);
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        int month = date.get(Calendar.MONTH);
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        int week = date.get(Calendar.WEEK_OF_YEAR);
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (month == 0 && week > 51) {
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            year--;
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        } else if (month == 11 && week == 1) {
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            year++;
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return year;
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    public static int getWeekForDate(Calendar date) {
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return date.get(Calendar.WEEK_OF_YEAR);
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @Override
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    protected void setCurrentDate(int year, int week) {
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        Calendar date = createDateFromWeek(year, week);
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (date.before(getMinDate())) {
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            setCurrentDate(getMinDate());
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        } else if (date.after(getMaxDate())) {
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            setCurrentDate(getMaxDate());
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        } else {
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            setCurrentDate(date);
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    private int getNumberOfWeeks(int year) {
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Create a date in the middle of the year, where the week year matches the year.
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        Calendar date = createDateFromWeek(year, 20);
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return date.getActualMaximum(Calendar.WEEK_OF_YEAR);
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    /**
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     * @return The selected year.
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     */
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @Override
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    public int getYear() {
101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return getISOWeekYearForDate(getCurrentDate());
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    /**
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     * @return The selected week.
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     */
107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    public int getWeek() {
108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return getWeekForDate(getCurrentDate());
109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @Override
112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    public int getPositionInYear() {
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return getWeek();
114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @Override
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    protected int getMaxYear() {
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return getISOWeekYearForDate(getMaxDate());
119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @Override
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    protected int getMinYear() {
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return getISOWeekYearForDate(getMinDate());
124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @Override
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    protected int getMaxPositionInYear(int year) {
12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (year == getISOWeekYearForDate(getMaxDate())) {
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            return getWeekForDate(getMaxDate());
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        return getNumberOfWeeks(year);
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @Override
13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    protected int getMinPositionInYear(int year) {
13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (year == getISOWeekYearForDate(getMinDate())) {
137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            return getWeekForDate(getMinDate());
138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return 1;
140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
142