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
|
// 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.
#include "ash/system/time/event_date_formatter_util.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/model/clock_model.h"
#include "ash/system/model/system_tray_model.h"
#include "ash/system/time/calendar_utils.h"
#include "ash/system/time/date_helper.h"
#include "base/i18n/number_formatting.h"
#include "base/i18n/time_formatting.h"
#include "base/time/time.h"
#include "google_apis/calendar/calendar_api_response_types.h"
#include "ui/base/l10n/l10n_util.h"
namespace ash::event_date_formatter_util {
namespace {
bool Is12HourClock() {
return Shell::Get()->system_tray_model()->clock()->hour_clock_type() ==
base::k12HourClock;
}
// Calculate the number of elapsed days so far.
// We add 1 as if 1 day has passed in the event, then we're on Day 2.
// `selected_date_midnight` will be the selected date at 00:00:00 UTC.
// `selected_date_midnight_utc` will be the selected date adjusted for local
// timezone in UTC.
int GetEventElapsedDayCount(const google_apis::calendar::CalendarEvent* event,
const base::Time& selected_date_midnight,
const base::Time& selected_date_midnight_utc) {
// For all day events, we can just take selected midnight UTC minus the
// event start time, as all day events start at midnight UTC.
if (event->all_day_event()) {
return (selected_date_midnight - event->start_time().date_time()).InDays() +
1;
}
// For other events, we take the adjusted to local selected midnight minus the
// adjusted to local midnight event start time.
const auto start_time_local_midnight =
DateHelper::GetInstance()->GetLocalMidnight(
event->start_time().date_time());
return (selected_date_midnight_utc - start_time_local_midnight).InDays() + 1;
}
int GetEventTotalDayCount(const google_apis::calendar::CalendarEvent* event) {
const auto start_time = calendar_utils::GetStartTimeMidnightAdjusted(event);
const auto end_time = calendar_utils::GetEndTimeMidnightAdjusted(event);
const int total_day_count = (end_time - start_time).InDays();
// Events ending at midnight of the following day that the event ends, i.e.
// all day events or multi-day events that finish at midnight in the local
// timezone, shouldn't be included in the total day count.
// `base::Time::InDays()` will be correct for these events, e.g. a 2 day,
// all day event with start and end times of 20220101 00:00:00 UTC - 20220103
// 00:00:00 UTC will be calculated as 2 days in time. Technically the event
// spans a 3 day period, but we want to show this as a 2 day event.
const auto end_time_adjusted = calendar_utils::GetEndTimeAdjusted(event);
base::Time::Exploded exploded_end_time;
end_time_adjusted.UTCExplode(&exploded_end_time);
auto event_ends_at_midnight =
(exploded_end_time.hour == 0 && exploded_end_time.minute == 0);
if (event->all_day_event() || event_ends_at_midnight)
return total_day_count;
// For multi-day events not ending at midnight, they'll span multiple days,
// but the `base::Time::InDays()` function will return 1 less than the total
// amount of days that an event might span e.g. for a 2 day, multi-day
// event of 20220101 08:00:00 UTC - 20220102 08:00:00 UTC, the elapsed
// time is 1 day, but it spans over 2 days.
return total_day_count + 1;
}
// Calculates the total and elapsed number of days for the event.
// Returns "(Day n / n)".
const std::u16string GetEventDayText(
const google_apis::calendar::CalendarEvent* event,
const base::Time& selected_date_midnight,
const base::Time& selected_date_midnight_utc) {
const int elapsed_day_count = GetEventElapsedDayCount(
event, selected_date_midnight, selected_date_midnight_utc);
const int total_day_count = GetEventTotalDayCount(event);
return l10n_util::GetStringFUTF16(IDS_ASH_CALENDAR_EVENT_ENTRY_DAYS_ELAPSED,
base::FormatNumber(elapsed_day_count),
base::FormatNumber(total_day_count));
}
} // namespace
ASH_EXPORT const std::tuple<std::u16string, std::u16string>
GetStartAndEndTimeAccessibleNames(base::Time start_time, base::Time end_time) {
if (Is12HourClock()) {
return std::make_tuple(calendar_utils::GetTwelveHourClockTime(start_time),
calendar_utils::GetTwelveHourClockTime(end_time));
}
return std::make_tuple(calendar_utils::GetTwentyFourHourClockTime(start_time),
calendar_utils::GetTwentyFourHourClockTime(end_time));
}
ASH_EXPORT const std::u16string GetFormattedInterval(base::Time start_time,
base::Time end_time) {
if (Is12HourClock()) {
return calendar_utils::FormatTwelveHourClockTimeInterval(start_time,
end_time);
}
return calendar_utils::FormatTwentyFourHourClockTimeInterval(start_time,
end_time);
}
ASH_EXPORT const std::u16string GetMultiDayText(
const google_apis::calendar::CalendarEvent* event,
const base::Time& selected_date_midnight,
const base::Time& selected_date_midnight_utc) {
const auto day_text = GetEventDayText(event, selected_date_midnight,
selected_date_midnight_utc);
// Returns "(Day n / n)".
if (event->all_day_event())
return day_text;
const auto end_time_local_midnight =
calendar_utils::GetEndTimeMidnightAdjusted(event);
const auto [start_time, end_time] = GetStartAndEndTimeAccessibleNames(
event->start_time().date_time(), event->end_time().date_time());
// Returns "Starts at `start_time` `day_text`.
if (selected_date_midnight < end_time_local_midnight) {
return l10n_util::GetStringFUTF16(
IDS_ASH_CALENDAR_EVENT_ENTRY_STARTS_AT_TIME, start_time, day_text);
}
// Returns "Ends at `end_time` `day_text`.
if (selected_date_midnight == end_time_local_midnight) {
return l10n_util::GetStringFUTF16(IDS_ASH_CALENDAR_EVENT_ENTRY_ENDS_AT_TIME,
end_time, day_text);
}
NOTREACHED()
<< "The `selected_date_midnight` is past the end of the event. Value is: "
<< selected_date_midnight;
}
} // namespace ash::event_date_formatter_util
|