https://www.timeanddate.com/date/weekday.html calcule divers faits concernant un jour de l'année, par exemple:
Étant donné une date arbitraire, comment ces nombres peuvent-ils être calculés avec la spécification chrono C ++ 20 ?
https://www.timeanddate.com/date/weekday.html calcule divers faits concernant un jour de l'année, par exemple:
Étant donné une date arbitraire, comment ces nombres peuvent-ils être calculés avec la spécification chrono C ++ 20 ?
Réponses:
C'est remarquablement facile avec la spécification chrono C ++ 20 . Ci-dessous, je montre une fonction qui entre une date arbitraire et imprime ces informations cout
. Bien qu'au moment d'écrire ces lignes, la spécification de chrono C ++ 20 n'est pas encore disponible, elle est approximée par une bibliothèque open-source gratuite . Vous pouvez donc l'expérimenter aujourd'hui, et même l'inclure dans les applications d'expédition tant que vous adoptez C ++ 11 ou une version ultérieure.
Cette réponse prendra la forme d'une fonction:
void info(std::chrono::sys_days sd);
sys_days
est une précision de jour time_point
dans la system_clock
famille. Cela signifie qu'il s'agit simplement d'un nombre de jours depuis le 1970-01-01 00:00:00 UTC. L'alias de type sys_days
est nouveau avec C ++ 20, mais le type sous-jacent est disponible depuis C ++ 11 ( time_point<system_clock, duration<int, ratio<86400>>>
). Si vous utilisez la bibliothèque d'aperçu open-source C ++ 20 , sys_days
est dans namespace date
.
Le code ci-dessous suppose une fonction locale:
using namespace std;
using namespace std::chrono;
pour réduire la verbosité. Si vous expérimentez avec la bibliothèque d'aperçu open-source C ++ 20 , supposez également:
using namespace date;
Titre
La sortie des deux premières lignes est simple:
cout << format("{:%d %B %Y is a %A}\n", sd)
<< "\nAdditional facts\n";
Il suffit de prendre la date sd
et de l'utiliser format
avec les drapeaux familiers strftime
/ put_time
pour imprimer la date et le texte. La bibliothèque d'aperçu open-source C ++ 20 n'a pas encore intégré la bibliothèque fmt , et utilise donc la chaîne de format légèrement modifiée "%d %B %Y is a %A\n"
.
Cela produira (par exemple):
26 December 2019 is a Thursday
Additional facts
Résultats intermédiaires communs calculés une fois
Cette section de la fonction est écrite en dernier, car on ne sait pas encore quels calculs seront nécessaires plusieurs fois. Mais une fois que vous savez, voici comment les calculer:
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;
Nous aurons besoin des champs année et mois de sd
et du weekday
(jour de la semaine). Il est efficace de les calculer une fois pour toutes de cette manière. Nous aurons également besoin (plusieurs fois) des premier et dernier jours de l'année en cours. Il est difficile de dire à ce stade, mais il est efficace de stocker ces valeurs en tant que type sys_days
car leur utilisation ultérieure ne l'est qu'avec une arithmétique orientée vers le jour qui sys_days
est très efficace à (vitesses inférieures à la nanoseconde).
Fait 1: nombre de jours de l'année et nombre de jours restants dans l'année
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";
Cela imprime le numéro de jour de l'année, le 1er janvier étant le jour 1, puis imprime également le nombre de jours restants dans l'année, sans inclure sd
. Le calcul pour ce faire est trivial. La division de chaque résultat par days{1}
permet d'extraire le nombre de jours dans dn
et dl
en un type intégral à des fins de formatage.
Fait 2: Numéro de ce jour de semaine et nombre total de jours de semaine dans l'année
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
est le jour de la semaine (du lundi au dimanche) calculé en haut de cet article. Pour effectuer ce calcul, nous avons d'abord besoin des dates du premier et du dernier wd
de l'année y
. y/1/wd[1]
est le premier wd
en janvier et y/12/wd[last]
le dernier wd
en décembre.
Le nombre total de wd
s dans l'année n'est que le nombre de semaines entre ces deux dates (plus 1). La sous-expression last_wd - first_wd
est le nombre de jours entre les deux dates. En divisant ce résultat par 1 semaine, vous obtenez un type intégral contenant le nombre de semaines entre les deux dates.
Le numéro de la semaine se fait de la même manière que le nombre total de semaines , sauf un commence par le jour en cours au lieu de la dernière wd
de l'année: sd - first_wd
.
Fait 3: Numéro de ce jour de semaine et nombre total de jours de semaine dans le mois
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);
Cela fonctionne exactement comme le fait 2, sauf que nous commençons par le premier et le dernier wd
s de la paire année-mois y/m
au lieu de l'année entière.
Fait 4: Nombre de jours dans l'année
auto total_days = LastDayOfYear - NewYears + days{1};
cout << format("* Year {:%Y} has ", y) << total_days/days{1} << " days.\n";
Le code parle à peu près de lui-même.
Fait 5 Nombre de jours dans le mois
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";
L'expression y/m/last
est le dernier jour de la paire année-mois y/m
, et bien sûr y/m/1
le premier jour du mois. Les deux sont convertis en sys_days
afin qu'ils puissent être soustraits pour obtenir le nombre de jours entre eux. Ajoutez 1 pour le nombre basé sur 1.
Utilisation
info
peut être utilisé comme ceci:
info(December/26/2019);
ou comme ça:
info(floor<days>(system_clock::now()));
Voici un exemple de sortie:
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.
Éditer
Pour ceux qui ne sont pas friands de la "syntaxe conventionnelle", il existe une "syntaxe constructeur" complète qui peut être utilisée à la place.
Par exemple:
sys_days NewYears = y/1/1;
sys_days first_wd = y/1/wd[1];
sys_days last_wd = y/12/wd[last];
peut être remplacé par:
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';
(qui, heureusement, est presque toujours pris au moment de la compilation, mais qui est toujours une gêne). Je serais donc prudent lors de l'utilisation de ce nouvel abus d'opérateur de division.