215 lines
7.1 KiB
Dart
215 lines
7.1 KiB
Dart
// Copyright 2017 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:ui' show hashValues;
|
|
import 'package:flutter/widgets.dart';
|
|
|
|
import 'material_localizations.dart';
|
|
|
|
/// Whether the [TimeOfDay] is before or after noon.
|
|
enum DayPeriod {
|
|
/// Ante meridiem (before noon).
|
|
am,
|
|
|
|
/// Post meridiem (after noon).
|
|
pm,
|
|
}
|
|
|
|
/// A value representing a time during the day, independent of the date that
|
|
/// day might fall on or the time zone.
|
|
///
|
|
/// The time is represented by [hour] and [minute] pair. Once created, both
|
|
/// values cannot be changed.
|
|
///
|
|
/// You can create TimeOfDay using the constructor which requires both hour and
|
|
/// minute or using [DateTime] object.
|
|
/// Hours are specified between 0 and 23, as in a 24-hour clock.
|
|
///
|
|
/// ### Sample code
|
|
///
|
|
/// ```dart
|
|
/// TimeOfDay now = TimeOfDay.now();
|
|
/// TimeOfDay releaseTime = TimeOfDay(hour: 15, minute: 0); // 3:00pm
|
|
/// TimeOfDay roomBooked = TimeOfDay.fromDateTime(DateTime.parse('2018-10-20 16:30:04Z')); // 4:30pm
|
|
/// ```
|
|
///
|
|
/// See also:
|
|
///
|
|
/// * [showTimePicker], which returns this type.
|
|
/// * [MaterialLocalizations], which provides methods for formatting values of
|
|
/// this type according to the chosen [Locale].
|
|
/// * [DateTime], which represents date and time, and is subject to eras and
|
|
/// time zones.
|
|
@immutable
|
|
class TimeOfDay {
|
|
/// Creates a time of day.
|
|
///
|
|
/// The [hour] argument must be between 0 and 23, inclusive. The [minute]
|
|
/// argument must be between 0 and 59, inclusive.
|
|
const TimeOfDay({ @required this.hour, @required this.minute });
|
|
|
|
/// Creates a time of day based on the given time.
|
|
///
|
|
/// The [hour] is set to the time's hour and the [minute] is set to the time's
|
|
/// minute in the timezone of the given [DateTime].
|
|
TimeOfDay.fromDateTime(DateTime time) : hour = time.hour, minute = time.minute;
|
|
|
|
/// Creates a time of day based on the current time.
|
|
///
|
|
/// The [hour] is set to the current hour and the [minute] is set to the
|
|
/// current minute in the local time zone.
|
|
factory TimeOfDay.now() { return TimeOfDay.fromDateTime(DateTime.now()); }
|
|
|
|
/// The number of hours in one day, i.e. 24.
|
|
static const int hoursPerDay = 24;
|
|
|
|
/// The number of hours in one day period (see also [DayPeriod]), i.e. 12.
|
|
static const int hoursPerPeriod = 12;
|
|
|
|
/// The number of minutes in one hour, i.e. 60.
|
|
static const int minutesPerHour = 60;
|
|
|
|
/// Returns a new TimeOfDay with the hour and/or minute replaced.
|
|
TimeOfDay replacing({ int hour, int minute }) {
|
|
assert(hour == null || (hour >= 0 && hour < hoursPerDay));
|
|
assert(minute == null || (minute >= 0 && minute < minutesPerHour));
|
|
return TimeOfDay(hour: hour ?? this.hour, minute: minute ?? this.minute);
|
|
}
|
|
|
|
/// The selected hour, in 24 hour time from 0..23.
|
|
final int hour;
|
|
|
|
/// The selected minute.
|
|
final int minute;
|
|
|
|
/// Whether this time of day is before or after noon.
|
|
DayPeriod get period => hour < hoursPerPeriod ? DayPeriod.am : DayPeriod.pm;
|
|
|
|
/// Which hour of the current period (e.g., am or pm) this time is.
|
|
int get hourOfPeriod => hour - periodOffset;
|
|
|
|
/// The hour at which the current period starts.
|
|
int get periodOffset => period == DayPeriod.am ? 0 : hoursPerPeriod;
|
|
|
|
/// Returns the localized string representation of this time of day.
|
|
///
|
|
/// This is a shortcut for [MaterialLocalizations.formatTimeOfDay].
|
|
String format(BuildContext context) {
|
|
debugCheckHasMediaQuery(context);
|
|
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
|
|
return localizations.formatTimeOfDay(
|
|
this,
|
|
alwaysUse24HourFormat: MediaQuery.of(context).alwaysUse24HourFormat,
|
|
);
|
|
}
|
|
|
|
@override
|
|
bool operator ==(dynamic other) {
|
|
if (other is! TimeOfDay)
|
|
return false;
|
|
final TimeOfDay typedOther = other;
|
|
return typedOther.hour == hour
|
|
&& typedOther.minute == minute;
|
|
}
|
|
|
|
@override
|
|
int get hashCode => hashValues(hour, minute);
|
|
|
|
@override
|
|
String toString() {
|
|
String _addLeadingZeroIfNeeded(int value) {
|
|
if (value < 10)
|
|
return '0$value';
|
|
return value.toString();
|
|
}
|
|
|
|
final String hourLabel = _addLeadingZeroIfNeeded(hour);
|
|
final String minuteLabel = _addLeadingZeroIfNeeded(minute);
|
|
|
|
return '$TimeOfDay($hourLabel:$minuteLabel)';
|
|
}
|
|
}
|
|
|
|
/// Determines how the time picker invoked using [showTimePicker] formats and
|
|
/// lays out the time controls.
|
|
///
|
|
/// The time picker provides layout configurations optimized for each of the
|
|
/// enum values.
|
|
enum TimeOfDayFormat {
|
|
/// Corresponds to the ICU 'HH:mm' pattern.
|
|
///
|
|
/// This format uses 24-hour two-digit zero-padded hours. Controls are always
|
|
/// laid out horizontally. Hours are separated from minutes by one colon
|
|
/// character.
|
|
HH_colon_mm,
|
|
|
|
/// Corresponds to the ICU 'HH.mm' pattern.
|
|
///
|
|
/// This format uses 24-hour two-digit zero-padded hours. Controls are always
|
|
/// laid out horizontally. Hours are separated from minutes by one dot
|
|
/// character.
|
|
HH_dot_mm,
|
|
|
|
/// Corresponds to the ICU "HH 'h' mm" pattern used in Canadian French.
|
|
///
|
|
/// This format uses 24-hour two-digit zero-padded hours. Controls are always
|
|
/// laid out horizontally. Hours are separated from minutes by letter 'h'.
|
|
frenchCanadian,
|
|
|
|
/// Corresponds to the ICU 'H:mm' pattern.
|
|
///
|
|
/// This format uses 24-hour non-padded variable-length hours. Controls are
|
|
/// always laid out horizontally. Hours are separated from minutes by one
|
|
/// colon character.
|
|
H_colon_mm,
|
|
|
|
/// Corresponds to the ICU 'h:mm a' pattern.
|
|
///
|
|
/// This format uses 12-hour non-padded variable-length hours with a day
|
|
/// period. Controls are laid out horizontally in portrait mode. In landscape
|
|
/// mode, the day period appears vertically after (consistent with the ambient
|
|
/// [TextDirection]) hour-minute indicator. Hours are separated from minutes
|
|
/// by one colon character.
|
|
h_colon_mm_space_a,
|
|
|
|
/// Corresponds to the ICU 'a h:mm' pattern.
|
|
///
|
|
/// This format uses 12-hour non-padded variable-length hours with a day
|
|
/// period. Controls are laid out horizontally in portrait mode. In landscape
|
|
/// mode, the day period appears vertically before (consistent with the
|
|
/// ambient [TextDirection]) hour-minute indicator. Hours are separated from
|
|
/// minutes by one colon character.
|
|
a_space_h_colon_mm,
|
|
}
|
|
|
|
/// Describes how hours are formatted.
|
|
enum HourFormat {
|
|
/// Zero-padded two-digit 24-hour format ranging from "00" to "23".
|
|
HH,
|
|
|
|
/// Non-padded variable-length 24-hour format ranging from "0" to "23".
|
|
H,
|
|
|
|
/// Non-padded variable-length hour in day period format ranging from "1" to
|
|
/// "12".
|
|
h,
|
|
}
|
|
|
|
/// The [HourFormat] used for the given [TimeOfDayFormat].
|
|
HourFormat hourFormat({ @required TimeOfDayFormat of }) {
|
|
switch (of) {
|
|
case TimeOfDayFormat.h_colon_mm_space_a:
|
|
case TimeOfDayFormat.a_space_h_colon_mm:
|
|
return HourFormat.h;
|
|
case TimeOfDayFormat.H_colon_mm:
|
|
return HourFormat.H;
|
|
case TimeOfDayFormat.HH_dot_mm:
|
|
case TimeOfDayFormat.HH_colon_mm:
|
|
case TimeOfDayFormat.frenchCanadian:
|
|
return HourFormat.HH;
|
|
}
|
|
|
|
return null;
|
|
}
|