1. Changelog
- 
     R0 - 
       First submission 
 
- 
       
2. Motivation and Scope
    The time library defines several value classes and class templates in
the 
    std::chrono
     namespace. All of the following are
copyable and comparable for equality (and some are also default
constructible, therefore satisfying 
- 
     duration 
- 
     time_point 
- 
     day 
- 
     month 
- 
     year 
- 
     weekday 
- 
     weekday_indexed 
- 
     weekday_last 
- 
     month_day 
- 
     month_day_last 
- 
     month_weekday 
- 
     month_weekday_last 
- 
     year_month 
- 
     year_month_day 
- 
     year_month_day_last 
- 
     year_month_weekday 
- 
     year_month_weekday_last 
- 
     zoned_time 
- 
     leap_second 
Unfortunately, none of these classes comes with an enabled 
std :: unordered_set < std :: chrono :: milliseconds > unique_measurements ; // ERROR 
Of course users can work around this limitation by providing a custom hash, for instance something like this:
struct duration_hash { template < class Rep , class Period > constexpr auto operator ()( const std :: chrono :: duration < Rep , Period > & d ) const noexcept ( /* ... */ ) { std :: hash < Rep > h ; return h ( d . count ()); } }; std :: unordered_set < std :: chrono :: milliseconds , duration_hash > unique_measurements ; // OK 
This limitation seems however to be unnecessarily vexing. Most of the types listed above can actually have a straightforward implementation for their hashing function, and there’s little justification for the Standard Library itself not to provide it.
The only case where a slightly more challenging implementation may be
required is 
3. Impact On The Standard
This proposal is a pure library addition.
This proposal does not depend on any other library extensions.
This proposal does not require any changes in the core language.
4. Design Decisions
4.1. What about time_zone 
   While 
The same reasoning applies to 
5. Technical Specifications
All the proposed changes are relative to [N4910].
5.1. Feature testing macro
In [version.syn], modify
#define __cpp_lib_chrono 201907L YYYYMML // also in <chrono> 
by replacing the existing value with the year and month of adoption of the present proposal.
5.2. Proposed wording
Add the following at the end of [time.syn]:
namespace std { // ???, hash support template < class T > struct hash ; template < class Rep , class Period > struct hash < chrono :: duration < Rep , Period >> ; template < class Clock , class Duration > struct hash < chrono :: time_point < Clock , Duration >> ; template <> struct hash < chrono :: day > ; template <> struct hash < chrono :: month > ; template <> struct hash < chrono :: year > ; template <> struct hash < chrono :: weekday > ; template <> struct hash < chrono :: weekday_indexed > ; template <> struct hash < chrono :: weekday_last > ; template <> struct hash < chrono :: month_day > ; template <> struct hash < chrono :: month_day_last > ; template <> struct hash < chrono :: month_weekday > ; template <> struct hash < chrono :: month_weekday_last > ; template <> struct hash < chrono :: year_month > ; template <> struct hash < chrono :: year_month_day > ; template <> struct hash < chrono :: year_month_day_last > ; template <> struct hash < chrono :: year_month_weekday > ; template <> struct hash < chrono :: year_month_weekday_last > ; template < class Duration , class TimeZonePtr > struct hash < chrono :: zoned_time < Duration , TimeZonePtr >> ; template <> struct hash < chrono :: leap_second > ; } 
Add a new subclause after [time.parse], with the following content:
??? Hash support [time.hash]template < class Rep , class Period > struct hash < chrono :: duration < Rep , Period >> ; (1) Letting D be
, the specializationchrono :: duration < Rep , Period > is enabled ([unord.hash]) if and only ifhash < D > is enabled. When enabled, for an objecthash < Rep > of typed ,D evaluates to the same value ashash < D > ()( d ) . The member functions are not guaranteed to behash < Rep > ()( d . count ()) .noexcept template < class Clock , class Duration > struct hash < chrono :: time_point < Clock , Duration >> ; (2) Letting TP be
, the specializationchrono :: time_point < Clock , Duration > is enabled ([unord.hash]) if and only ifhash < TP > is enabled. When enabled, for an objecthash < Duration > of typetp ,TP evaluates to the same value ashash < TP > ()( tp ) . The member functions are not guaranteed to behash < Duration > ()( tp . time_since_epoch ()) .noexcept template <> struct hash < chrono :: day > ; template <> struct hash < chrono :: month > ; template <> struct hash < chrono :: year > ; template <> struct hash < chrono :: weekday > ; template <> struct hash < chrono :: weekday_indexed > ; template <> struct hash < chrono :: weekday_last > ; template <> struct hash < chrono :: month_day > ; template <> struct hash < chrono :: month_day_last > ; template <> struct hash < chrono :: month_weekday > ; template <> struct hash < chrono :: month_weekday_last > ; template <> struct hash < chrono :: year_month > ; template <> struct hash < chrono :: year_month_day > ; template <> struct hash < chrono :: year_month_day_last > ; template <> struct hash < chrono :: year_month_weekday > ; template <> struct hash < chrono :: year_month_weekday_last > ; (3) The specialization is enabled ([unord.hash]).
template < class Duration , class TimeZonePtr > struct hash < chrono :: zoned_time < Duration , TimeZonePtr >> ; (4) Letting ZT be
, the specializationchrono :: zoned_time < Duration , TimeZonePtr > is enabled ([unord.hash]) if and only ifhash < ZT > is enabled andhash < Duration > is enabled. The member functions are not guaranteed to behash < TimeZonePtr > .noexcept template <> struct hash < chrono :: leap_second > ; (5) The specialization is enabled ([unord.hash]).
6. Acknowledgements
Thanks to KDAB for supporting this work.
Thanks to Howard Hinnant for designing 
All remaining errors are ours and ours only.