https://www.timeanddate.com/date/weekday.html oblicza różne fakty dotyczące dnia roku, na przykład:
Biorąc pod uwagę dowolną datę, w jaki sposób można obliczyć te liczby ze specyfikacją chronografu C ++ 20 ?
https://www.timeanddate.com/date/weekday.html oblicza różne fakty dotyczące dnia roku, na przykład:
Biorąc pod uwagę dowolną datę, w jaki sposób można obliczyć te liczby ze specyfikacją chronografu C ++ 20 ?
Odpowiedzi:
Jest to niezwykle łatwe dzięki specyfikacji chronografu C ++ 20 . Poniżej pokazuję funkcję, która wprowadza dowolną datę i wypisuje tę informację na cout
. Chociaż w chwili pisania tego tekstu specyfikacja chronografu C ++ 20 nie jest jeszcze dostępna, jest ona aproksymowana przez bezpłatną bibliotekę typu open source . Możesz więc eksperymentować z nim już dziś, a nawet uwzględnić go w aplikacjach wysyłkowych, o ile zastosujesz C ++ 11 lub nowszy.
Ta odpowiedź przybierze postać funkcji:
void info(std::chrono::sys_days sd);
sys_days
to precyzja dnia time_point
w system_clock
rodzinie. Oznacza to, że jest to po prostu liczba dni od 1970-01-01 00:00:00 UTC. Alias typu sys_days
jest nowy w C ++ 20, ale typ podstawowy jest dostępny od C ++ 11 ( time_point<system_clock, duration<int, ratio<86400>>>
). Jeśli używasz biblioteki podglądu C ++ 20 typu open source , sys_days
jest w namespace date
.
Poniższy kod zakłada lokalną funkcję:
using namespace std;
using namespace std::chrono;
w celu zmniejszenia gadatliwości. Jeśli eksperymentujesz z biblioteką podglądu C ++ 20 typu open source , załóż również:
using namespace date;
Nagłówek
Wyprowadzenie pierwszych dwóch wierszy jest proste:
cout << format("{:%d %B %Y is a %A}\n", sd)
<< "\nAdditional facts\n";
Po prostu weź datę sd
i użyj format
ze znanymi strftime
/ put_time
flagami, aby wydrukować datę i tekst. C ++ 20 podgląd biblioteki open-source nie został jeszcze zintegrowany z biblioteki FMT , a więc korzysta z lekko zmienioną ciąg formatu "%d %B %Y is a %A\n"
.
Spowoduje to wyświetlenie (na przykład):
26 December 2019 is a Thursday
Additional facts
Wspólne wyniki pośrednie obliczane raz
Ta sekcja funkcji jest zapisywana jako ostatnia, ponieważ nie wiadomo jeszcze, jakie obliczenia będą potrzebne wiele razy. Ale kiedy już wiesz, oto jak je obliczyć:
year_month_day ymd = sd;
auto y = ymd.year();
auto m = ymd.month();
weekday wd{sd};
sys_days NewYears = y/1/1;
sys_days LastDayOfYear = y/12/31;
Będziemy potrzebować pól roku i miesiąca sd
oraz weekday
(dnia tygodnia). Skuteczne jest obliczenie ich raz na zawsze w ten sposób. Będziemy także potrzebować (wiele razy) pierwszy i ostatni dzień bieżącego roku. Trudno w tym momencie powiedzieć, ale efektywne jest przechowywanie tych wartości jako typu, sys_days
ponieważ ich późniejsze użycie jest tylko z arytmetyką zorientowaną na dzień, która sys_days
jest bardzo wydajna przy (prędkościach poniżej nanosekundowych).
Fakt 1: liczba dni w roku i liczba dni pozostałych w roku
auto dn = sd - NewYears + days{1};
auto dl = LastDayOfYear - sd;
cout << "* It is day number " << dn/days{1} << " of the year, "
<< dl/days{1} << " days left.\n";
Spowoduje to wydrukowanie numeru dnia roku, przy czym 1 stycznia jest dniem 1, a następnie wydrukowanie liczby dni pozostałych w roku, bez uwzględnienia sd
. Obliczenia tego są trywialne. Podzielenie wyniku przez każdy days{1}
jest sposób wydobycia liczby dni dn
i dl
w integralny typu dla celów formatowania.
Fakt 2: Liczba dni tygodnia i całkowita liczba dni tygodnia w roku
sys_days first_wd = y/1/wd[1];
sys_days last_wd = y/12/wd[last];
auto total_wd = (last_wd - first_wd)/weeks{1} + 1;
auto n_wd = (sd - first_wd)/weeks{1} + 1;
cout << format("* It is {:%A} number ", wd) << n_wd << " out of "
<< total_wd << format(" in {:%Y}.\n}", y);
wd
to dzień tygodnia (od poniedziałku do niedzieli) obliczony na początku tego artykułu. Aby wykonać to obliczenie, najpierw potrzebujemy daty pierwszego i ostatniego wd
roku y
. y/1/wd[1]
jest pierwszy wd
w styczniu, a y/12/wd[last]
ostatni wd
w grudniu.
Całkowita liczba wd
s w ciągu roku to tylko liczba tygodni między tymi dwiema datami (plus 1). Podwyrażenie last_wd - first_wd
to liczba dni między dwiema datami. Dzielenie tego wyniku przez 1 tydzień powoduje, że typem integralnym jest liczba tygodni między dwiema datami.
Liczba tygodni odbywa się tak samo, jak w ogólnej liczbie tygodni wyjątkiem jednego startów z bieżącego dnia zamiast ostatniego wd
roku: sd - first_wd
.
Fakt 3: Liczba dni tygodnia i całkowita liczba dni tygodnia w miesiącu
first_wd = y/m/wd[1];
last_wd = y/m/wd[last];
total_wd = (last_wd - first_wd)/weeks{1} + 1;
n_wd = (sd - first_wd)/weeks{1} + 1;
cout << format("* It is {:%A} number }", wd) << n_wd << " out of "
<< total_wd << format(" in {:%B %Y}.\n", y/m);
Działa to tak, jak w Fact 2, tyle że zaczynamy od pierwszej i ostatniej wd
pary pary rok-miesiąc y/m
zamiast przez cały rok.
Fakt 4: Liczba dni w roku
auto total_days = LastDayOfYear - NewYears + days{1};
cout << format("* Year {:%Y} has ", y) << total_days/days{1} << " days.\n";
Kod mówi sam za siebie.
Fakt 5 Liczba dni w miesiącu
total_days = sys_days{y/m/last} - sys_days{y/m/1} + days{1};
cout << format("* {:%B %Y} has ", y/m) << total_days/days{1} << " days.\n";
Wyrażenie y/m/last
to ostatni dzień pary rok-miesiąc y/m
i oczywiście y/m/1
pierwszy dzień miesiąca. Oba są konwertowane na sys_days
, aby można je było odjąć, aby uzyskać liczbę dni między nimi. Dodaj 1 dla liczby opartej na 1.
Posługiwać się
info
można użyć w następujący sposób:
info(December/26/2019);
lub tak:
info(floor<days>(system_clock::now()));
Oto przykładowy wynik:
26 December 2019 is a Thursday
Additional facts
* It is day number 360 of the year, 5 days left.
* It is Thursday number 52 out of 52 in 2019.
* It is Thursday number 4 out of 4 in December 2019.
* Year 2019 has 365 days.
* December 2019 has 31 days.
Edytować
Dla tych, którzy nie lubią „konwencjonalnej składni”, dostępna jest pełna „składnia konstruktora”.
Na przykład:
sys_days NewYears = y/1/1;
sys_days first_wd = y/1/wd[1];
sys_days last_wd = y/12/wd[last];
można zastąpić:
sys_days NewYears = year_month_day{y, month{1}, day{1}};
sys_days first_wd = year_month_weekday{y, month{1}, weekday_indexed{wd, 1}};
sys_days last_wd = year_month_weekday_last{y, month{12}, weekday_last{wd}};
std::cout << "a*b = " << a*b << "; a^b = " << a^b << '\n';
(które na szczęście prawie zawsze jest łapane w czasie kompilacji, ale nadal jest uciążliwe). Byłbym więc ostrożny przy użyciu tego nowego nadużycia operatora oddziału.