https://www.timeanddate.com/date/weekday.html menghitung berbagai fakta tentang hari dalam setahun, misalnya:
Diberikan tanggal sewenang-wenang, bagaimana angka-angka ini dapat dihitung dengan spesifikasi chrono C ++ 20 ?
https://www.timeanddate.com/date/weekday.html menghitung berbagai fakta tentang hari dalam setahun, misalnya:
Diberikan tanggal sewenang-wenang, bagaimana angka-angka ini dapat dihitung dengan spesifikasi chrono C ++ 20 ?
Jawaban:
Ini sangat mudah dengan spesifikasi chrono C ++ 20 . Di bawah ini saya menunjukkan fungsi yang menginput tanggal sewenang-wenang, dan mencetak informasi ini ke cout
. Padahal pada saat penulisan ini, spesifikasi ch ++ C ++ 20 belum dikirimkan, diperkirakan oleh pustaka sumber terbuka yang gratis . Jadi Anda dapat bereksperimen dengannya hari ini, dan bahkan memasukkannya dalam aplikasi pengiriman selama Anda mengadopsi C ++ 11 atau lebih baru.
Jawaban ini akan mengambil bentuk fungsi:
void info(std::chrono::sys_days sd);
sys_days
adalah ketelitian sehari time_point
dalam system_clock
keluarga. Itu berarti hanya hitungan hari sejak 1970-01-01 00:00:00 UTC. Tipe alias sys_days
baru dengan C ++ 20, tetapi tipe yang mendasarinya telah tersedia sejak C ++ 11 ( time_point<system_clock, duration<int, ratio<86400>>>
). Jika Anda menggunakan pustaka pratinjau C ++ 20 sumber terbuka , sys_days
ada di namespace date
.
Kode di bawah ini mengasumsikan fungsi-lokal:
using namespace std;
using namespace std::chrono;
untuk mengurangi verbositas. Jika Anda bereksperimen dengan pustaka pratinjau C ++ 20 sumber terbuka , asumsikan juga:
using namespace date;
Tajuk
Untuk menghasilkan dua baris pertama adalah sederhana:
cout << format("{:%d %B %Y is a %A}\n", sd)
<< "\nAdditional facts\n";
Ambil saja tanggal sd
dan gunakan format
dengan familiar strftime
/ put_time
bendera untuk mencetak tanggal dan teks. The open-source C ++ 20 perpustakaan pratinjau belum terintegrasi perpustakaan fmt , dan menggunakan format string sedikit diubah"%d %B %Y is a %A\n"
.
Ini akan menampilkan (misalnya):
26 December 2019 is a Thursday
Additional facts
Hasil antara umum dihitung sekali
Bagian fungsi ini ditulis terakhir, karena seseorang belum tahu perhitungan apa yang akan dibutuhkan beberapa kali. Tapi begitu Anda tahu, inilah cara menghitungnya:
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;
Kita akan membutuhkan bidang tahun dan bulan sd
, dan weekday
(hari dalam seminggu). Adalah efisien untuk menghitungnya sekali dan untuk semua dengan cara ini. Kami juga akan membutuhkan (beberapa kali) hari-hari pertama dan terakhir tahun berjalan. Sulit untuk mengatakan pada saat ini, tetapi efisien untuk menyimpan nilai-nilai ini sebagai jenis sys_days
sebagai penggunaan selanjutnya mereka hanya dengan hari-berorientasi aritmatika yang sys_days
merupakan sangat efisien (kecepatan sub-nanodetik).
Fakta 1: jumlah hari dalam setahun, dan jumlah hari tersisa dalam tahun
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";
Ini mencetak jumlah hari dalam setahun, dengan 1 Januari menjadi hari 1, dan kemudian juga mencetak jumlah hari yang tersisa di tahun itu, tidak termasuk sd
. Perhitungan untuk melakukan ini sepele. Membagi setiap hasil dengan days{1}
cara untuk mengekstraksi jumlah hari dalam dn
dan dl
menjadi tipe integral untuk tujuan pemformatan.
Fakta 2: Jumlah hari kerja ini dan jumlah hari kerja dalam setahun
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
adalah hari dalam seminggu (Senin hingga Minggu) yang dihitung di bagian atas artikel ini. Untuk melakukan perhitungan ini, pertama-tama kita perlu tanggal yang pertama dan terakhir wd
di tahun tersebut y
. y/1/wd[1]
adalah yang pertama wd
di bulan Januari, dan y/12/wd[last]
yang terakhir wd
di bulan Desember.
Jumlah total wd
s dalam tahun ini hanya jumlah minggu antara kedua tanggal ini (ditambah 1). Sub-ekspresi last_wd - first_wd
adalah jumlah hari antara dua tanggal. Membagi hasil ini dengan 1 minggu menghasilkan tipe integral yang menahan jumlah minggu antara kedua tanggal.
Jumlah minggu dilakukan dengan cara yang sama dengan jumlah total minggu kecuali satu dimulai dengan hari saat ini bukan yang terakhir wd
tahun ini: sd - first_wd
.
Fakta 3: Jumlah hari kerja ini dan jumlah hari kerja dalam sebulan
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);
Ini berfungsi seperti Fakta 2, kecuali kita mulai dengan pasangan pertama dan terakhir wd
dari pasangan tahun-bulan, y/m
bukan sepanjang tahun.
Fakta 4: Jumlah hari dalam setahun
auto total_days = LastDayOfYear - NewYears + days{1};
cout << format("* Year {:%Y} has ", y) << total_days/days{1} << " days.\n";
Kode ini cukup banyak berbicara sendiri.
Fakta 5 Jumlah hari dalam sebulan
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";
Ungkapannya y/m/last
adalah hari terakhir dari pasangan tahun-bulan y/m
, dan tentu saja y/m/1
adalah hari pertama bulan itu. Keduanya dikonversi sys_days
sehingga mereka dapat dikurangkan untuk mendapatkan jumlah hari di antara mereka. Tambahkan 1 untuk hitungan berbasis 1.
Menggunakan
info
dapat digunakan seperti ini:
info(December/26/2019);
atau seperti ini:
info(floor<days>(system_clock::now()));
Berikut ini contoh output:
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.
Edit
Bagi mereka yang tidak menyukai "sintaksis konvensional", ada "sintaks konstruktor" lengkap yang dapat digunakan sebagai gantinya.
Sebagai contoh:
sys_days NewYears = y/1/1;
sys_days first_wd = y/1/wd[1];
sys_days last_wd = y/12/wd[last];
dapat diganti dengan:
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';
(yang, untungnya, hampir selalu tertangkap pada waktu kompilasi, tetapi masih mengganggu). Jadi saya akan berhati-hati ketika menggunakan penyalahgunaan operator divisi baru ini.