auto time = last_write_time(iter->path());
time_t tt = decltype(time)::clock::to_time_t(time); // Note: to_time_t not guaranteed to exist.
tm tmt;
localtime_s(&tmt, &tt);
cout << std::put_time<wchar_t>(&tmt, L"%F %T") << std::endl;
So the most pressing issue is that (at least according to cppreference.com) the std::filesystem::file_time_type::clock type only has to satisfy the TrivialClock concept, which does not imply that it has a to_time_t method at all (i.e. it doesn't have to be the system_clock). Is this an oversight, an error in cppreference.com's description or am I missing some other way to convert the filesystem::file_time_type object to a printable type? The code above is fairly similar to what replyers come up with on stack overflow: (https://stackoverflow.com/questions/12835577/how-to-convert-stdchronotime-point-to-calendar-datetime-string-with-fraction) so it seems that there is no more straight forward way.
Apart from this specification problem I think that there should be a pure C++ way of formatting time_points that does not involve ancient C functions and multiple steps (getting higher precision than a second makes my code even more complicated).
One way would be to provide an overload of put_time that takes a system_clock::time_point and a similar function that returns the formatted string. A way to get sub-second fractions should be available as (%f is actually free according to strftime documentation at cppreference.com). As put_time is dependant on the locale facet imbued on the stream a string conversion function would probably need to have a locale parameter which defaults to the global locale of the process.
A similar shortcut without C middlemen would be appropriate for scanning time values, I presume.
In C++17 we got the new type timespec and the function to get the current time, timespec_get(). However there does not seem to be a link from this C struct (?) to any of the chrono functionality or filesystem times. Also there does not seem to exist a formatting function which handles formatting including the fractions (see the example here: http://en.cppreference.com/w/cpp/chrono/c/timespec_get).
an error in cppreference.com's description
> - It seems that the procedure for creating year_month_day may be a little overworked, involving several other data types with overloaded / operators and user defined literals. Also, if you don't "use" the date namespace and this gets standardized all those types will have long names like std::date::year, or maybe std::chrono::year if this functionality is integrated with chrono. As these names are the same as the usual names you would prefer to use for your variables it can get messy, and with a using statement it downright clashes and you have to give your variables cryptic names.
>
> void MyFunction(int year, int month, int day)
> {
> auto dt = std::date::year(year) / month / day;
> }
The current proposal is to put these into namespace chrono. And my current C++11/14/17 usage of chrono almost always resorts to “using namespace std::chrono” at function scope as I’m already frustrated with:
auto min = std::chrono::time_point_cast<std::chrono::minutes>(std::chrono::system_clock::now());
I write instead:
using namespace std::chrono;
auto min = time_point_cast<minutes>(system_clock::now());
With just one component needing qualification as in your example, I might not bother with the using declaration. But by the time I have to qualify two components, I am so done with that.
You can also write MyFunction like this:
void MyFunction(int y, int m, int d)
{
using namespace std::chrono;
auto dt = year_month_day{year{year}, month{m}, day{d}};
}
The overall picture, as with <chrono>, is to reduce to a minimum the conversions you do between an untyped system (i.e. int) and a typed system where unit mixups are compile-time errors instead of run time errors:
void MyFunction(std::chrono::year y, std::chrono::month m, std::chrono::day d)
{
auto dt = y/m/d;
}
Like <chrono> my lib continues the tradition of strong type safety to catch as many errors as possible at compile-time.
We force people into such dangerous conversion points today mostly with I/O, and so I’m trying to alleviate that with good I/O support.
> also the use of the slash operator is not that obvious as many parts of the world (and ISO8601) are more at ease with using - between the parts. Using an overloaded operator when the operation is not consistent with the usual meaning of the operator is also generally discouraged (No, I don't like path / path either). Maybe use + as it is neutral between different notations of dates and actually seems to be consistent: You are actually adding years, days and months to make a complete date. On the other hand doing this without first casting all the ints to their corresponding year, day and month types seems strange if you view it as addition.
+ and - have the wrong precedence:
2017_y+jan - 2015_y+sep
vs
2017_y/jan - 2015_y/sep == months{16}
and can easily lead to confusing expressions like this:
2015_y+sep+months{16}
vs
2015_y/sep + months{16} == 2017_y/jan
But if you really just don’t like the ’/‘ syntax, you’re not alone. Others feel the same way. Feel free to use the constructor syntax instead:
year_month{2017_y, jan} - year_month{2015_y, sep} == months{16}
or:
year_month{year{2017}, month{1}} - year_month{year{2015}, month{9}} == months{16}
instead of:
2017_y/jan - 2015_y/sep == months{16}
Just don’t tell everyone else that they _have_ to use the constructor syntax instead of the ‘/‘ syntax (unless you want to enforce that as a coding guideline on a project you’re in charge of). Because there’s lots of people who really like the ‘/‘ syntax. This lib provides both, with no performance, functionality or type-safety penalties for using either.
> A library which is more complicated than its task warrants risks not being used as the benefit may not outweigh the learning curve.
True, that’s why I’ve been field testing this lib for a couple of years now. The field testing is actually going pretty well. This library strives for a simple, self-consistent API. But simple doesn’t always mean “do it the way it has always been done in the past”, or even “don’t have too many types.” My experience from <chrono> is that many people said simple means “don’t use templates.”. And indeed, reading the <chrono> header is a good way to get terrified of that library. But the code people usually write with <chrono> is simple, readable and type-safe.
Ditto with this library that extends <chrono> to calendars.
I’m leaning heavily on modern features like auto and user-defined literals which reduce the need to remember so many type names:
auto today = 8_d/jun/2017; // has type year_month_day
auto tomorrow = fri[2]/jun/2017; // has type year_month_weekday
Similarly, auto is of great help with <chrono> itself, in deducing the resultant type of “mixed-mode” arithmetic across time_points and durations of varying precisions.
> date::year_month_day date = date::year(2017)/2/4;
> date::year_month_weekday wdate = date::sys_days(date);
> return wdate.weekday();
>
> In wxWidgets, by contrast, you can do:
>
> wxDate date(2, 4, 2017);
> return date.GetDayOfWeek();
This will do it;
using namespace date::literals;
return date::weekday{feb/4/2017}; // or did you mean 2_d/apr/2017? so hard to tell when your only tool is int
> This level of simplicity is what we should strive for.
The wxWidgets code is actually unreadable to me. I can not read that and know what date you mean without breaking out the wxWidgets documentation. Such ambiguity is not possible in my date lib. Ambiguity is a compile-time error.
I feel pretty strongly that this library should build on <chrono>. The central theme of this library is that time_point<system_clock, Duration> _is_ the “linear” datetime representation. Choose any precision you want, it is already in your <chrono> header. Everything else is just helpers for converting to and from calendars. And that very design decision is what will make I/O on file_time_type so convenient, functional and easy.
>
>
> Now back to more nitpicking:
>
> - The definition of months (the duration) is a bit scary as it relates to an "average month length" which means that it will not accurately represent the current month when used as a duration from a year's start. Is it really needed? I guess the same can be said for years, which tries to subsume the concept of leap years but where presumably the number of years since the start of another year can be off by one on Jan 1 or Dec 31.
months can be used both as a chrono::duration (when used with a chrono time_point), getting what you describe above. This is useful for doing chronological computations on physical processes that don’t respect human calendars (e.g. changing weather patterns or mammalian gestation periods). For example:
auto t = system_clock::now() + months{18}; // about 18 months from now
months can also be used as a calendrical duration when used with calendrical types and subtypes such as year_month_day and year_month. This is useful for doing calendrical computations when you require days of the month to match up, for example:
static_assert(2017_y/jan/3 + months{18} == jul/3/2018);
Both chronological and calendrical use cases have value, and are easy to do.
> - It seems strange to me that the 12/24 hour format is part of the time_of_day object. Shouldn't this be a formatting issue when converting to a string rather than a member of the object?
This may well disappear. time_of_day was born as a formatting aid, and predates the more generalized format function.
>
> - In general I don't like the idea of having different specializations with different API (such as time_of_day<minutes> having a minutes() function while time_of_day<hours> has not). Maybe minutes() could always exist but return 0 for a hour-only specialization? I understand it as your idea being to save implementation bits when not needed.
The different types have come in useful in the same manner that different types are useful for durations, instead of just say timespec. But the major client of time_of_day has in practice been format/parse, and so time_of_day may not need to be part of the API. That being said, some clients like to do their own formatting/parsing and time_of_day is useful for them.
>
> - format() should take its fmt parameter as a basic_string_view. [this is likely fixed in the standardization proposal]
Agreed. I haven’t done so in the lib as I get a fair number of requests to support older compilers. I have a small but growing list of such details that should change for the proposal (the next revision of which I need to finish within a week and a half).
>
> - Maybe it would be better if format's char types for the returned string and for the fmt parameter were decoupled. I write maybe as this decoupling would require callers to explicitly name the char type they want for the returned string. A name convention as used for basic_string itself could solve this, possibly.
Nope. That design has already irritated me enough when trying to write generic code with to_string/to_wstring.
>
> - The name format() could be a bit too generic, especially if the format("{}, is a nice {}", ...) proposal gets standardized.
Agreed, though overloading with the type-safe arguments may also address this issue.
> Instead I would suggest integrating the functionality intended here into a general format() method so that the formatting parameters are "strftime like" if the corresponding argument is of a date/time related type as proposed here. This would also work nicely with string translation, so that locale specific formats can be used if needed (without involving a locale parameter).
I anticipate a cooperative integration of these two libraries if they both find their way into the standardization process. I think there could be a strong synergy there.
>
> - A problem with parsing dates entered by users is that persons tend to not type dates in a coherent way. A remedy I have used is to allow multiple format strings which are tried in succession. This could fall outside a standard library but as the standard allows for two distinct output formats per locale it does not seem too far fetched to allow at least two on input. One possible way to define this would be to reserve one character, such as | as a separator in format strings when used for input, with the meaning that each | separated part is one complete format to be tried in order. Obviously it would be up to the programmer to place the formats in a suitable order to avoid ambiguities.
I can’t reserve “|”, but I could reserve “%|”. Or perhaps multiple parse fmt string arguments? Would not be difficult to write as an add-on. Here’s how I did this with two parsing formats:
https://stackoverflow.com/a/38839725/576911
Interesting idea, thanks.
Howard
double GetCurrentTime() {system_clock::time_point n = system_clock::now();time_t st = system_clock::to_time_t(n);int nanoseconds = duration_cast<nanoseconds>(n) - duration_cast<nanoseconds>(seconds(st));return st + double(nanoseconds) * 0.000000001;}
double GetCurrentTime(){
return duration<double>(system_clock::now().time_since_epoch()).count();
}
double GetCurrentTime(){
return duration<double>(system_clock::now() - system_clock::from_time_t(0)).count();
}
> - It seems that the procedure for creating year_month_day may be a little overworked, involving several other data types with overloaded / operators and user defined literals. Also, if you don't "use" the date namespace and this gets standardized all those types will have long names like std::date::year, or maybe std::chrono::year if this functionality is integrated with chrono. As these names are the same as the usual names you would prefer to use for your variables it can get messy, and with a using statement it downright clashes and you have to give your variables cryptic names.I think we may have to disagree on this. For me <chrono> seems very much too complicated for what it actually offers most users. I can see that to cater for every usage in the universe with utmost storage space efficiency you may have to make everything a template like this, but for a vast majority of uses using double for both time_point and duration would have sufficed. The precision is microseconds in a century which must be well beyond most needs. Alternatively a 64 bit integer representation similar to timespec with suitable functions and operators. As 64 bits gives nanosecond precision for 580 years there seems to be little need for anything else outside very specific physics areas.While you with your intimate knowledge of <chrono> may find it easy to use as you have the whole history of developing it to fall back on, it surely is not easy to grasp when you start to use it. I think it was Bjarne who stated it so aptly: "Let's not confuse familiarity with simplicity". Everything can't be expected to be done in simple ways, but getting the current time can.
Much of the problem seems to be that the standard does not define: a) a way to know the resolution of a clock object, b) the epoch of a clock object as a date. Without this information it is very hardto get a wall clock time out of a clock object and know what precision I have. Surely, I can do a duration cast to nanoseconds, but I don't know what precision I actually get.
As for the epoch it seems that the only way is to retrieve the time_t (only available on system_clock) which is defined to be relative to 1970-01-01. So to get the number of seconds since this epoch with decimals
Ditto with this library that extends <chrono> to calendars.
I’m leaning heavily on modern features like auto and user-defined literals which reduce the need to remember so many type names:
auto today = 8_d/jun/2017; // has type year_month_day
auto tomorrow = fri[2]/jun/2017; // has type year_month_weekday
Similarly, auto is of great help with <chrono> itself, in deducing the resultant type of “mixed-mode” arithmetic across time_points and durations of varying precisions.
> date::year_month_day date = date::year(2017)/2/4;
> date::year_month_weekday wdate = date::sys_days(date);
> return wdate.weekday();
>
> In wxWidgets, by contrast, you can do:
>
> wxDate date(2, 4, 2017);
> return date.GetDayOfWeek();
This will do it;
using namespace date::literals;
return date::weekday{feb/4/2017}; // or did you mean 2_d/apr/2017? so hard to tell when your only tool is intOk, I was unaware that you can construct a weekday, (and I assume day, month, etc [upon reading date.h it seems I was assuming wrongly: only weekday has this type of constructor]) a complete date and it will "extract" the relevant information. That seems like a nice feature.Can you also do:auto wd = date::day{system_clock::now()}; // Day in month right nowIf not, why?
> This level of simplicity is what we should strive for.
The wxWidgets code is actually unreadable to me. I can not read that and know what date you mean without breaking out the wxWidgets documentation. Such ambiguity is not possible in my date lib. Ambiguity is a compile-time error.Unless you want to play hide and seek with the compiler you would still need to open the documentation if you are not already a pro. With wxDateTime you have all functionality related to dates and times in one class and thus the documentation is similarly close by when you need it. Or type a dot in the IDE if you forgot the exact method name and it will be shown in a dropdown list, most likely. (No 12 history entries in your browser).
I feel pretty strongly that this library should build on <chrono>. The central theme of this library is that time_point<system_clock, Duration> _is_ the “linear” datetime representation. Choose any precision you want, it is already in your <chrono> header. Everything else is just helpers for converting to and from calendars. And that very design decision is what will make I/O on file_time_type so convenient, functional and easy.Lets hope for that.
>
>
> Now back to more nitpicking:
>
> - The definition of months (the duration) is a bit scary as it relates to an "average month length" which means that it will not accurately represent the current month when used as a duration from a year's start. Is it really needed? I guess the same can be said for years, which tries to subsume the concept of leap years but where presumably the number of years since the start of another year can be off by one on Jan 1 or Dec 31.
months can be used both as a chrono::duration (when used with a chrono time_point), getting what you describe above. This is useful for doing chronological computations on physical processes that don’t respect human calendars (e.g. changing weather patterns or mammalian gestation periods). For example:
auto t = system_clock::now() + months{18}; // about 18 months from now
months can also be used as a calendrical duration when used with calendrical types and subtypes such as year_month_day and year_month. This is useful for doing calendrical computations when you require days of the month to match up, for example:
static_assert(2017_y/jan/3 + months{18} == jul/3/2018);Are you saying that this assert will not fail for any date pairs? Surely 2017_y/feb/1 + month(1) will not be march/1/2017 as february is so short?
Is it possible to construct a complete date from year + week number + day within week? If so, what type do I get?