C ++ 20 क्रोनो का उपयोग करना, दिनांक के बारे में विभिन्न तथ्यों की गणना करना


19

https://www.timeanddate.com/date/weekday.html वर्ष के एक दिन के बारे में विभिन्न तथ्यों की गणना करता है, उदाहरण के लिए:

https://i.stack.imgur.com/WPWuO.png

एक मनमानी तिथि को देखते हुए, इन नंबरों की गणना C ++ 20 क्रोनो विनिर्देशन के साथ कैसे की जा सकती है ?


2
"... और हम सभी को पता है कि आईएसओ सप्ताह 1 कब है, ठीक है? ..." - "नहीं, लेकिन मुझे एक पुस्तकालय मिला है" ... :-) - ब्रेकर हॉवर्ड!
टेड लिंग्गो

Stackoverflow.com/q/59391132/560648 (अब हटा दिया गया) से लिया गया चित्र । शर्म की बात है कि इसे हटा दिया गया क्योंकि इस सवाल का जवाब होना चाहिए था।
कक्षा

सही बात। मैंने उस एक को फिर से खोलने के लिए मतदान किया।
हावर्ड हिनांट

जवाबों:


22

यह C ++ 20 क्रोनो विनिर्देशन के साथ उल्लेखनीय रूप से आसान है । नीचे मैं एक फ़ंक्शन दिखाता हूं जो एक मनमाना तिथि इनपुट करता है, और इस जानकारी को प्रिंट करता है cout। हालांकि इस लेखन के समय, C ++ 20 क्रोनो विनिर्देश अभी तक शिपिंग नहीं है, यह एक स्वतंत्र, ओपन-सोर्स लाइब्रेरी द्वारा अनुमानित है । तो आप इसे आज प्रयोग कर सकते हैं, और यहां तक ​​कि शिपिंग अनुप्रयोगों में भी शामिल कर सकते हैं जब तक आप C ++ 11 या बाद में अपनाते हैं।

यह उत्तर एक फ़ंक्शन का रूप लेगा:

void info(std::chrono::sys_days sd);

sys_daysपरिवार time_pointमें एक दिन की सटीकता है system_clock। इसका मतलब है कि यह 1970-01-01 से 00:00:00 यूटीसी के बाद के दिनों की गिनती है। sys_daysC ++ 20 के साथ प्रकार उपनाम अन्य है, लेकिन अंतर्निहित प्रकार C ++ 11 ( time_point<system_clock, duration<int, ratio<86400>>>) के बाद से उपलब्ध है । यदि आप ओपन-सोर्स C ++ 20 प्रीव्यू लाइब्रेरी का उपयोग करते हैं , sys_daysतो में है namespace date

फ़ंक्शन-स्थानीय मान के नीचे कोड:

using namespace std;
using namespace std::chrono;

वाचालता को कम करने के लिए। यदि आप ओपन-सोर्स C ++ 20 प्रीव्यू लाइब्रेरी के साथ प्रयोग कर रहे हैं , तो यह भी मान लें:

using namespace date;

शीर्षक

आउटपुट के लिए पहली दो लाइनें सरल हैं:

cout << format("{:%d %B %Y is a %A}\n", sd)
     << "\nAdditional facts\n";

बस तारीख ले लो sdऔर formatपरिचित strftime/ put_timeझंडे के साथ तारीख और पाठ का प्रिंट आउट लेने के लिए उपयोग करें। ओपन-सोर्स सी ++ 20 पूर्वावलोकन पुस्तकालय अभी उपलब्ध नहीं है fmt पुस्तकालय , और इसलिए थोड़ा बदल प्रारूप स्ट्रिंग का उपयोग करता है "%d %B %Y is a %A\n"

यह आउटपुट (उदाहरण के लिए) होगा:

26 December 2019 is a Thursday

Additional facts

सामान्य मध्यवर्ती परिणाम एक बार गणना की जाती है

फ़ंक्शन का यह खंड अंतिम रूप से लिखा गया है, क्योंकि किसी को अभी तक यह पता नहीं है कि कई बार गणना की क्या आवश्यकता होगी। लेकिन एक बार जब आप जान जाते हैं, तो उनकी गणना कैसे करें:

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;

हमें वर्ष और महीने के क्षेत्र sd, और weekdayसप्ताह का दिन) की आवश्यकता होगी। इस तरीके से एक बार और सभी के लिए उनकी गणना करना कुशल है। हमें वर्तमान वर्ष के पहले और अंतिम दिनों में भी (कई बार) की आवश्यकता होगी। इस बिंदु पर बताना कठिन है, लेकिन इन मूल्यों को इस प्रकार स्टोर करना कुशल है sys_daysक्योंकि उनका बाद का उपयोग केवल दिन-उन्मुख अंकगणित के साथ होता sys_daysहै, जो (उप-नैनोसेकंड गति) पर बहुत कुशल होता है ।

तथ्य 1: वर्ष की दिन संख्या, और वर्ष में बचे दिनों की संख्या

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";

यह वर्ष के दिन की संख्या को प्रिंट करता है, जिसमें 1 जनवरी का दिन 1 होता है, और फिर वर्ष में शेष दिनों की संख्या को भी प्रिंट करता है, जिसमें शामिल नहीं है sd। ऐसा करने की गणना तुच्छ है। प्रत्येक परिणाम को विभाजित करना , फॉर्मेटिंग उद्देश्यों के लिए days{1}दिनों की संख्या dnऔर dlअभिन्न प्रकार में निकालने का एक तरीका है।

तथ्य 2: इस सप्ताह के दिनों की संख्या और वर्ष में कुल दिनों की संख्या

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इस लेख के शीर्ष पर गणना की गई सप्ताह का दिन (सोमवार थ्रू संडे) है। इस अभिकलन को करने के लिए हमें पहले wdवर्ष में पहले और अंतिम तारीखों की आवश्यकता होती है y। जनवरी में y/1/wd[1]पहला wdहै, और दिसंबर में y/12/wd[last]आखिरी wdहै।

वर्ष की कुल संख्या wdइन दो तिथियों (प्लस 1) के बीच के सप्ताहों की संख्या है। उप-अभिव्यक्ति last_wd - first_wdदो तिथियों के बीच दिनों की संख्या है। इस परिणाम को 1 सप्ताह तक विभाजित करने से दो तिथियों के बीच एक अभिन्न प्रकार धारण किया जाता है।

सप्ताह संख्या को उसी तरह से किया जाता है जैसे कि सप्ताह की कुल संख्या को छोड़कर, वर्तमान wdवर्ष के बजाय वर्तमान दिन से शुरू होता है sd - first_wd:।

तथ्य 3: इस सप्ताह के दिनों की संख्या और महीने में कुल दिनों की संख्या

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);

यह फैक्ट 2 की तरह ही काम करता है, सिवाय इसके कि हम पूरे साल के बजाय wdसाल-महीने की पहली और आखिरी जोड़ी से y/mशुरुआत करें।

तथ्य 4: वर्ष में दिनों की संख्या

auto total_days = LastDayOfYear - NewYears + days{1};
cout << format("* Year {:%Y} has ", y) << total_days/days{1} << " days.\n";

कोड बहुत ज्यादा खुद के लिए बोलता है।

तथ्य 5 महीने में दिनों की संख्या

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";

अभिव्यक्ति y/m/lastवर्ष-महीने की जोड़ी का अंतिम दिन है y/m, और निश्चित रूप y/m/1से महीने का पहला दिन है। दोनों को इस तरह परिवर्तित किया जाता sys_daysहै कि उनके बीच की संख्या प्राप्त करने के लिए उन्हें घटाया जा सके। 1-आधारित गणना के लिए 1 जोड़ें।

उपयोग

info इस तरह इस्तेमाल किया जा सकता है:

info(December/26/2019);

या इस तरह:

info(floor<days>(system_clock::now()));

यहाँ उदाहरण आउटपुट है:

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.

संपादित करें

जो लोग "पारंपरिक वाक्यविन्यास" के शौकीन नहीं हैं, उनके लिए एक पूर्ण "कंस्ट्रक्टर सिंटैक्स" है जिसका उपयोग इसके बजाय किया जा सकता है।

उदाहरण के लिए:

sys_days NewYears = y/1/1;
sys_days first_wd = y/1/wd[1];
sys_days last_wd = y/12/wd[last];

द्वारा प्रतिस्थापित किया जा सकता है:

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}};

5
डिवीजन ऑपरेटर का यह नया दुरुपयोग बिटशिफ्ट ऑपरेटरों के पुराने दुरुपयोग से भी बदतर है। यह मुझे दुखी करता है :(
डेव

2
अधिक गंभीर नोट पर, क्या मैं यह सुझाव दे सकता हूं कि आप अपने कुछ पूर्व-संकलित चर को उन खंडों में ले जाएं जो उनका उपयोग करते हैं? यह देखना थोड़ा अजीब है कि स्क्रॉल करने के लिए नीचे और देखने के लिए कि मान कहाँ से आते हैं और वे कैसे उत्पन्न हुए हैं। और आप अपने दिन-प्रति वर्ष के सामान को पहले विभाजन करके थोड़ा अव्यवस्थित कर सकते हैं, जैसे कि आपने हफ्तों के लिए किया था।
डेव

1
पूरी तरह असहमत। यह अच्छा लग रहा है, यह समझना आसान है और, विशेष रूप से, अधिक वर्बोज़ संस्करण की तुलना में पढ़ना आसान है।
कैसियो रेन

@ CássioRenan हो सकता है, लेकिन याद रखें कि वाक्यविन्यास का दुरुपयोग अक्सर अप्रत्याशित व्यवहार के साथ आता है। उपर्युक्त बिट पारियों के साथ, उदाहरण के लिए, std::cout << "a*b = " << a*b << "; a^b = " << a^b << '\n';(जो कि सौभाग्य से, लगभग हमेशा संकलन के समय पकड़ा जाता है, लेकिन अभी भी एक झुंझलाहट है) के व्यवहार पर ध्यान दें । इसलिए मैं इस नए डिवीजन ऑपरेटर के दुरुपयोग का उपयोग करते समय सतर्क रहूंगा।
रुस्लान

@Ruslan सावधानी हमेशा किसी भी नए पुस्तकालय के साथ warranted है। यही कारण है कि यह एक स्वतंत्र रूप से और सार्वजनिक रूप से 2015 के बाद से परीक्षण किया गया है। ग्राहकों से प्रतिक्रिया को डिजाइन में वापस शामिल किया गया है। यह मानकीकरण के लिए प्रस्तावित नहीं किया गया था जब तक कि यह सकारात्मक क्षेत्र के अनुभव के वर्षों का एक ठोस आधार नहीं था। विशेष रूप से, ऑपरेटरों के उपयोग को ऑपरेटर की प्रक्रिया को ध्यान में रखते हुए डिजाइन किया गया है, क्षेत्र का व्यापक रूप से परीक्षण किया गया है, और एक समान "कंस्ट्रक्टर एपीआई" के साथ आता है। देखें स्टार-history.t9t.io/#HowardHinnant/date&google/cctz और youtube.com/watch?v=tzyGjOm8AKo
हावर्ड हिनान्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.