1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
|
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_SYSTEM_TIME_DATE_HELPER_H_
#define ASH_SYSTEM_TIME_DATE_HELPER_H_
#include <string>
#include "ash/ash_export.h"
#include "ash/public/cpp/locale_update_controller.h"
#include "base/memory/singleton.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "chromeos/ash/components/settings/timezone_settings.h"
#include "third_party/icu/source/i18n/unicode/dtitvfmt.h"
#include "third_party/icu/source/i18n/unicode/dtptngen.h"
#include "third_party/icu/source/i18n/unicode/gregocal.h"
#include "third_party/icu/source/i18n/unicode/smpdtfmt.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"
namespace ash {
// A singleton class used to create and cache `GregorianCalendar`,
// `icu::SimpleDateFormat` and `icu::DateIntervalFormat` objects, so that they
// don't have to be recreated each time when querying the time difference or
// formatting a time. This improves performance since creating
// `icu::SimpleDateFormat` and `icu::DateIntervalFormat` objects is expensive.
class DateHelper : public LocaleChangeObserver,
public system::TimezoneSettings::Observer {
public:
// Returns the singleton instance.
ASH_EXPORT static DateHelper* GetInstance();
// Creates a formatter object used to format dates from the given `pattern`.
icu::SimpleDateFormat CreateSimpleDateFormatter(const char* pattern);
// Creates a formatter object used to format dates without calling the
// `getBestPattern` function, which resolves the input pattern to the best
// fit, which is not always what we want. e.g. 'mm' returns 'm' even though we
// want it zero-padded (03 vs. 3 when given 12:03)
icu::SimpleDateFormat CreateSimpleDateFormatterWithoutBestPattern(
const char* pattern);
// Creates a formatter object that extracts the hours field from a given date.
// Uses `pattern` to differentiate between 12 and 24 hour clock formats.
icu::SimpleDateFormat CreateHoursFormatter(const char* pattern);
// Creates a date interval formatter object that formats a `DateInterval` into
// text as compactly as possible.
// Note that even if a pattern does not request a certain date part, it will
// be automatically included if that part is different between two dates (e.g.
// for `pattern=hm` (hours and minutes in twelve hour clock format),
// "18 Nov 2021 8:30"..."18 Nov 2021 9:30" => "8:30 – 9:30 AM", but
// "18 Nov 2021 8:30"..."19 Nov 2021 7:20" =>
// "11/18/2021, 8:30 AM – 11/19/2021, 7:20 AM").
std::unique_ptr<icu::DateIntervalFormat> CreateDateIntervalFormatter(
const char* pattern);
// Returns a formatted string of a `time` using the given `formatter`.
std::u16string GetFormattedTime(const icu::DateFormat* formatter,
const base::Time& time);
// Returns a formatted interval string using the given `formatter`.
ASH_EXPORT std::u16string GetFormattedInterval(
const icu::DateIntervalFormat* formatter,
const base::Time& start_time,
const base::Time& end_time);
// Get the time difference to UTC time based on the time passed in and the
// system timezone. Daylight saving is considered.
ASH_EXPORT base::TimeDelta GetTimeDifference(base::Time date) const;
// Gets the local midnight in UTC time of the `date`.
// e.g. If the `date` is Apr 1st 1:00 (which is Mar 31st 18:00 PST), the
// local timezone is PST and time difference is 7 hrs. It returns Mar 31st
// 7:00, which is Mar 31st 00:00 PST.
ASH_EXPORT base::Time GetLocalMidnight(base::Time date);
icu::SimpleDateFormat& day_of_month_formatter() {
return day_of_month_formatter_;
}
icu::SimpleDateFormat& month_day_formatter() { return month_day_formatter_; }
icu::SimpleDateFormat& month_day_year_formatter() {
return month_day_year_formatter_;
}
icu::SimpleDateFormat& month_day_year_week_formatter() {
return month_day_year_week_formatter_;
}
icu::SimpleDateFormat& month_name_formatter() {
return month_name_formatter_;
}
icu::SimpleDateFormat& month_name_year_formatter() {
return month_name_year_formatter_;
}
icu::SimpleDateFormat& time_zone_formatter() { return time_zone_formatter_; }
icu::SimpleDateFormat& twelve_hour_clock_formatter() {
return twelve_hour_clock_formatter_;
}
icu::SimpleDateFormat& twenty_four_hour_clock_formatter() {
return twenty_four_hour_clock_formatter_;
}
icu::SimpleDateFormat& day_of_week_formatter() {
return day_of_week_formatter_;
}
icu::SimpleDateFormat& week_title_formatter() {
return week_title_formatter_;
}
icu::SimpleDateFormat& year_formatter() { return year_formatter_; }
icu::SimpleDateFormat& twelve_hour_clock_hours_formatter() {
return twelve_hour_clock_hours_formatter_;
}
icu::SimpleDateFormat& twenty_four_hour_clock_hours_formatter() {
return twenty_four_hour_clock_hours_formatter_;
}
icu::SimpleDateFormat& minutes_formatter() { return minutes_formatter_; }
const icu::DateIntervalFormat* twelve_hour_clock_interval_formatter() {
return twelve_hour_clock_interval_formatter_.get();
}
const icu::DateIntervalFormat* twenty_four_hour_clock_interval_formatter() {
return twenty_four_hour_clock_interval_formatter_.get();
}
std::vector<std::u16string> week_titles() { return week_titles_; }
// Reset after a locale change in the test.
ASH_EXPORT void ResetForTesting();
private:
friend base::DefaultSingletonTraits<DateHelper>;
friend class DateHelperUnittest;
DateHelper();
DateHelper(const DateHelper& other) = delete;
DateHelper& operator=(const DateHelper& other) = delete;
~DateHelper() override;
// Resets the icu::SimpleDateFormat objects after a time zone change.
ASH_EXPORT void ResetFormatters();
// Calculates the week titles based on the language setting.
ASH_EXPORT void CalculateLocalWeekTitles();
// system::TimezoneSettings::Observer:
void TimezoneChanged(const icu::TimeZone& timezone) override;
// LocaleChangeObserver:
// Although the device will restart whenever there's locale change and this
// instance will be re-constructed, however this dose not cover all the cases.
// The locale between the login screen and the user's screen can be different.
// (For example: different languages are set in different accounts, and the
// login screen will use the owener's locale setting.)
void OnLocaleChanged() override;
// Formatter for getting the day of month.
icu::SimpleDateFormat day_of_month_formatter_;
// Formatter for getting the month name and day of month.
icu::SimpleDateFormat month_day_formatter_;
// Formatter for getting the month name, day of month, and year.
icu::SimpleDateFormat month_day_year_formatter_;
// Formatter for getting the month, day, year and day of week.
icu::SimpleDateFormat month_day_year_week_formatter_;
// Formatter for getting the name of month.
icu::SimpleDateFormat month_name_formatter_;
// Formatter for getting the month name and year.
icu::SimpleDateFormat month_name_year_formatter_;
// Formatter for getting the time zone.
icu::SimpleDateFormat time_zone_formatter_;
// Formatter for 12 hour clock hours and minutes.
icu::SimpleDateFormat twelve_hour_clock_formatter_;
// Formatter for 24 hour clock hours and minutes.
icu::SimpleDateFormat twenty_four_hour_clock_formatter_;
// Formatter for getting the day of week. Returns 1 - 7.
icu::SimpleDateFormat day_of_week_formatter_;
// Formatter for getting the week title. e.g. M, T, W.
icu::SimpleDateFormat week_title_formatter_;
// Formatter for getting the year.
icu::SimpleDateFormat year_formatter_;
// Formatter for getting the hours in a 12 hour clock format.
icu::SimpleDateFormat twelve_hour_clock_hours_formatter_;
// Formatter for getting the hours in a 24 hour clock format.
icu::SimpleDateFormat twenty_four_hour_clock_hours_formatter_;
// Formatter for getting the minutes.
icu::SimpleDateFormat minutes_formatter_;
// Interval formatter for two dates. Formats time in twelve
// hour clock format (e.g. 8:30 – 9:30 PM or 11:30 AM – 2:30 PM).
std::unique_ptr<icu::DateIntervalFormat>
twelve_hour_clock_interval_formatter_;
// Interval formatter for two dates. Formats time in twenty
// four hour clock format (e.g. 20:30 – 21:30).
std::unique_ptr<icu::DateIntervalFormat>
twenty_four_hour_clock_interval_formatter_;
// Week title list based on the language setting. e.g. SMTWTFS in English.
std::vector<std::u16string> week_titles_;
std::unique_ptr<icu::GregorianCalendar> gregorian_calendar_;
base::ScopedObservation<system::TimezoneSettings,
system::TimezoneSettings::Observer>
time_zone_settings_observer_{this};
};
} // namespace ash
#endif // ASH_SYSTEM_TIME_DATE_HELPER_H_
|