ट्रैक
/
R
R
/
अभ्यास
/
ब्यूटी के लिए बुकिंग
ब्यूटी के लिए बुकिंग

ब्यूटी के लिए बुकिंग

सीखने का अभ्यास

परिचय

"डेट और समय वे चीज़ें हैं जो हम छोटे बच्चों को सिखाते हैं। यह कितना मुश्किल हो सकता है?"

कई प्रोग्रामरों ने यह गलती की है, और इसके बाद का अनुभव उनके स्वास्थ्य और खुशी पर बुरा असर डालता है।

डेट और समय के साथ जटिल प्रोग्रामिंग करने वाले किसी भी व्यक्ति को कम से कम संभावित समस्याओं को समझने और उन्हें कम करने के लिए तैयार रहना चाहिए।

यह दस्तावेज़ R द्वारा डेट और समय को संभालने का एक अवलोकन देने की कोशिश करेगा, लेकिन आगे के विवरणों के लिए पूरा डॉक्युमेंटेशन देखना ज़रूरी होगा।

एक डेटा साइंस भाषा होने के नाते, R में डेट और समय का विशेष महत्व है। बहुत सारा डेटा टाइम सीरीज़ के रूप में आता है: किसी बीमारी के प्रकोप के दौरान रोज़ाना के मरीज़ों की संख्या, सरकारों द्वारा बताए गए महीने के रोज़गार के आँकड़े, किसी घोंसले की कॉलोनी में पक्षियों की संख्या, बड़ी अर्थव्यवस्थाओं का सालाना जीडीपी, और ऐसे अनगिनत उदाहरण।

क्या इसका मतलब है कि R डेट और समय को संभालना आसान बना देता है?

दुख की बात है, नहीं!

Base R में डेट और समय की कार्यक्षमता की प्रतिष्ठा खराब है, और अब इसका बहुत कम उपयोग होता है।

lubridate पैकेज एक बड़ा सुधार है, लेकिन यह एक बड़ी और जटिल लाइब्रेरी है, जिसे बड़ी और जटिल समस्याओं की एक विस्तृत श्रृंखला को संभालने के लिए बनाया गया है, तो इसके लिए तैयार रहिए।

शुरू में यह स्वतंत्र था, लेकिन अब lubridate, tidyverse संग्रह के साथ शामिल कर दिया गया है। इसे library(lubridate) या library(tidyverse) से लोड कीजिए।

lubridate के साथ काम करने में मदद के लिए ये संसाधन हैं:

डेट और डेटटाइम

एक date बस एक दिन है, जिसमें समय की कोई जानकारी नहीं होती।

अंदरूनी रूप से, डेट को 1970-01-01 से बीते दिनों की (चिह्न सहित) संख्या के रूप में संग्रहीत किया जाता है।

today()
#> [1] "2026-04-22"

एक datetime डेट, समय और टाइमज़ोन की जानकारी को एक साथ रखता है।

अंदरूनी रूप से, इसे UTC टाइमज़ोन में 1970 की शुरुआत से बीते सेकंडों की संख्या के रूप में संग्रहीत किया जाता है।

now()
#> [1] "2026-04-22 15:37:11 MST"  # mid-afternoon in Arizona

शायद आश्चर्य की बात है कि R में सिर्फ़ समय वाली वैल्यू के लिए कोई अंदरूनी प्रतिनिधित्व नहीं है।

date और datetime वैल्यू के साथ काम करना

डेट/समय से जुड़ी शायद सबसे आम ज़रूरतें ये हैं:

  • किसी उपयुक्त इनपुट फॉर्मेट को पार्स करके डेट या डेटटाइम बनाना।
  • डेट या डेटटाइम से ज़रूरी संख्यात्मक या स्ट्रिंग फॉर्मेट निकालना।
  • किसी डेट या डेटटाइम वैल्यू पर ऑफसेट लगाना।
  • ऐसी दो वैल्यू के बीच का समय अंतराल निकालना।
  • मौजूदा डेट (today() से) और/या डेटटाइम (now() से) निकालना।

स्ट्रिंग से पार्स करना

डेट और समय लिखने के कई तरीके हैं, और ये अक्सर संस्कृति के हिसाब से अलग-अलग होते हैं। "7/6/23" जैसी सिर्फ़ संख्याओं वाली डेट अस्पष्ट और उलझाने वाली होती हैं, और इनके कारण बहुराष्ट्रीय संगठनों में कई महँगी गलतियाँ हुई हैं (लेखक यह अपने कड़वे निजी अनुभव से कह रहा है)।

अंतर्राष्ट्रीय मानक (y-m-d) को ISO 8601 में परिभाषित किया गया है, और इसके दो मुख्य फ़ायदे हैं:

  • पार्स करना तेज़ और स्पष्ट होता है।
  • छाँटना आसान होता है, क्योंकि डेटटाइम को सामान्य टेक्स्ट की तरह मानकर वर्णानुक्रम में छाँटा जा सकता है।

लेकिन डेटा साइंस का मतलब है जो भी डेटा मिले उसी के साथ काम करना, और दूसरे लोग उसे कैसे फॉर्मेट करते हैं, इसकी शिकायत करना अक्सर बेकार होता है।

Base R में कन्वर्ज़न फंक्शन हैं जो एक फॉर्मेट स्ट्रिंग लेते हैं (डिफ़ॉल्ट रूप से ISO 8601)।

as.Date("2026-04-22")
#> [1] "2026-04-22"
as.Date("4/22/26", format = "%m/%d/%y")
#> [1] "2026-04-22"
as.POSIXct("2026-04-22 15:30:09 MST")
#> [1] "2026-04-22 15:30:09 MST"

ये फॉर्मेट स्ट्रिंग दशकों पुराने strptime() फंक्शन जैसी हैं, जो कई भाषाओं में शामिल है। इस सिंटैक्स से परिचित प्रोग्रामर चाहें तो lubridate में fast_strptime() फंक्शन का उपयोग कर सकते हैं।

और भी मददगार बात यह है कि lubridate कई तरह के हेल्पर फंक्शन देता है, जिनके नाम फ़ील्ड के क्रम को दर्शाते हैं। एक बार जब फंक्शन को पता चल जाए कि किन वैल्यू को और किस क्रम में देखना है, तो पार्सिंग काफ़ी लचीली हो जाती है।

mdy("4/22/26")
#> [1] "2026-04-22"
mdy("April 22nd 26")
#> [1] "2026-04-22"
mdy("Wednesday, April 22nd 2026")
#> [1] "2026-04-22"
mdy_hm("Wednesday, April 22nd 2026, 4:14 pm")
#> [1] "2026-04-22 16:14:00 UTC"  # defaults to your OS timezone

संख्यात्मक वैल्यू से बनाना

ऐसी स्थितियों में जहाँ आपके प्रोग्राम के पास किसी डेट/डेटटाइम के अलग-अलग हिस्से संख्याओं के रूप में हों, उन्हें make_date() या make_datetime() से जोड़ा जा सकता है।

ये वे कंपोनेंट हैं जो दिए जा सकते हैं, साथ में उनका क्रम और डिफ़ॉल्ट वैल्यू दिखाई गई हैं:

make_datetime(
  year = 1970L,
  month = 1L,
  day = 1L,
  hour = 0L,
  min = 0L,
  sec = 0,
  tz = "UTC"
)
#> [1] "1970-01-01 UTC"


make_datetime(2026, 4, 22, 17)
#> [1] "2026-04-22 17:00:00 UTC"

स्वाभाविक रूप से, make_date() सिर्फ़ year, month और day आर्गुमेंट लेता है।

मनुष्य के पढ़ने लायक रूप में आउटपुट देना

R कंसोल डेट/डेटटाइम को अपने आप स्ट्रिंग के रूप में प्रदर्शित करता है। यह आमतौर पर सुविधाजनक होता है, लेकिन कभी-कभी भ्रमित करने वाला भी।

अंदरूनी रूप से, डेट और डेटटाइम संख्याएँ होती हैं (कुछ एट्रिब्यूट के साथ), स्ट्रिंग नहीं। जहाँ स्ट्रिंग की उम्मीद हो वहाँ डेट(टाइम) लौटाने से समस्याएँ होंगी, इसलिए हमें यह जानना ज़रूरी है कि यह कन्वर्ज़न कैसे किया जाए।

एक आसान तरीका है Base R के as.character() का उपयोग करना, जो ISO 8601 फॉर्मेट में एक स्ट्रिंग देता है।

डेटटाइम के लिए format_ISO8601() फंक्शन भी है, जिसमें किसी मनचाही सटीकता तक गोल करने के विकल्प हैं।

today() |> as.character()  # a date
#> [1] "2026-04-23"
now() |> as.character()  # a datetime
#> [1] "2026-04-23 09:07:09.779319"
now() |> format_ISO8601() # defaults to nearest second
#> [1] "2026-04-23T09:07:38"

बहुत कम गैर-प्रोग्रामर ISO 8601 आउटपुट देखना चाहते हैं, इसलिए संस्कृति-विशेष डेट/समय फॉर्मेट को संभालना ज़रूरी है।

Base R format() फंक्शन देता है, जो कई अन्य भाषाओं में शामिल पुराने strftime() फंक्शन जैसी फॉर्मेट स्ट्रिंग का उपयोग करता है।

format(today(), "%A, %d %B %Y")
#> [1] "Thursday, 23 April 2026"

Base R का यह तरीका भद्दा है, लेकिन भरोसेमंद है। यहाँ कुछ आम कोड दिए गए हैं:

कोड परिणाम
%d महीने के दिन की संख्या (5, 17, 28, आदि)
%a दिन का संक्षिप्त नाम (Mon, Tue, Wed, आदि)
%A दिन का पूरा नाम (Monday, Tuesday, आदि)
%w सप्ताह के दिन की संख्या (0-6, रविवार 0)
%u सप्ताह के दिन की संख्या (1-7, सोमवार 1)
%b महीने का संक्षिप्त नाम (Jan, Feb, आदि)
%B महीने का पूरा नाम (January, February, आदि)
%y 2 अंकों वाला वर्ष (जैसे 89)
%Y 4 अंकों वाला वर्ष (जैसे 1989)
%h घंटे (24-घंटे की घड़ी)
%m मिनट
%s सेकंड
%z UTC से ऑफसेट
%Z टाइम ज़ोन (कैरेक्टर)

lubridate stamp() फंक्शन के साथ एक अधिक मानव-अनुकूल विकल्प देने का लक्ष्य रखता है, और साथ ही ज़्यादा सीमित stamp_date() और stamp_time() भी।

ये एक टेम्पलेट स्ट्रिंग लेते हैं जो मनचाहे आउटपुट का एक उदाहरण होती है, और उस फॉर्मेट को बनाने वाला एक कस्टम फंक्शन बनाते हैं।

lubridate फॉर्मेट का अनुमान लगाने की कोशिश करता है, लेकिन अक्सर अस्पष्टताओं में फँस जाता है और गलत परिणाम देता है। अस्पष्टता दूर करने के लिए फॉर्मेट स्ट्रिंग (जैसे "dmy") देने के लिए तैयार रहिए।

Exercism के लिए, locale = "C" देकर अपने सिस्टम लोकेल को दरकिनार करना और अंग्रेज़ी में काम करना (जैसा टेस्ट अपेक्षा करते हैं) भी उपयोगी हो सकता है। लोकेल जटिल होते हैं!

sf <- stamp("Saturday, June 27, 2026 at 14:45", locale = "C")
#> Multiple formats matched: "%A, %B %d, %Y at %H:%M"(1), "Saturday, %Om %d, %Y at %H:%M"(1), "Saturday, %B %d, %Y at %H:%M"(1), "%A, %Om %d, %Y at %H:%M"(0)
#> Using: "%A, %B %d, %Y at %H:%M"

sf(make_datetime(2023, 3, 29, 15, 0, 0))
#> [1] "Wednesday, March 29, 2023 at 15:00"

कंपोनेंट सेट करना या निकालना

lubridate किसी डेट या डेटटाइम के एलिमेंट पाने या सेट करने के लिए कई फंक्शन देता है: year() और second() जैसे सामान्य फंक्शन, और साथ ही quarter() और epiweek() जैसे ज़्यादा विशेष फंक्शन भी।

ऐसे सभी फंक्शन किसी वैल्यू को पाने के लिए उपयोग किए जा सकते हैं, और ज़्यादातर वैल्यू सेट करने के लिए भी।

dt <- now()
dt
#> [1] "2026-04-23 15:47:11 MST"

# get
month(dt)
#> [1] 4

# set
month(dt) <- 11
dt
#> [1] "2026-11-23 15:47:11 MST"

wday() (सप्ताह का दिन) और month() के लिए डिफ़ॉल्ट आउटपुट पूर्णांक होता है, लेकिन:

  • labels = TRUE सेट करने पर मौजूदा लोकेल के अनुसार संक्षिप्त अक्षर स्ट्रिंग लौटती है।
  • साथ ही abbr = FALSE सेट करने पर पूरा नाम लौटता है।
d <- today()
d
#> [1] "2026-04-23"
wday(d)
#> [1] 5
wday(d, label = TRUE)
#> [1] Thu
#> Levels: Sun < Mon < Tue < Wed < Thu < Fri < Sat
wday(d, label = TRUE, abbr = FALSE)
#> [1] Thursday
#> Levels: Sunday < Monday < Tuesday < Wednesday < Thursday < Friday < Saturday

ये लेबल categorical variables हैं, जो एक और कॉन्सेप्ट का विषय होंगे। वैल्यू केवल सूचीबद्ध Levels तक सीमित होती हैं, जो छँटाई का क्रम भी दिखाते हैं।

डिफ़ॉल्ट रूप से सप्ताह रविवार से शुरू होता है, लेकिन इसे week_start आर्गुमेंट से बदला जा सकता है (सोमवार के लिए 1 दीजिए)।

dt <- make_datetime(2026, 4, 23)

# default behavior
wday(dt)
#> [1] 5
wday(dt, label = T)
#> [1] Thu

# set week_start to Monday
wday(dt, week_start = 1)
#> [1] 4

कुछ यूटिलिटी फंक्शन TRUE/FALSE वैल्यू लौटाते हैं, जैसे leap_year() और dst() (क्या डेलाइट सेविंग टाइम चालू है?)।

महीनों की लंबाई अलग-अलग होती है, इसलिए days_in_month() पूर्णांक वैल्यू देता है।

समय अंतराल

date और datetime दोनों वैल्यू समयरेखा पर एक क्षण को दर्शाती हैं।

"कल इसी समय" या "अब से एक सप्ताह बाद" जैसी अवधारणाओं को हम कैसे संभालते हैं?

अन्य विज्ञान-केंद्रित भाषाओं से परिचित विद्यार्थी Python के datetime.timedelta या Julia के Period टाइप से परिचित हो सकते हैं।

इसके विपरीत, R में समय अंतराल दर्शाने के कम से कम तीन तरीके हैं, जिनकी अपनी-अपनी खूबियाँ और सीमाएँ हैं। हमेशा की तरह, अपनी स्थिति के लिए सबसे उपयुक्त तरीका चुनिए।

अलग-अलग अंतराल को as.period(), as_duration() और as.interval() की मदद से आसानी से एक-दूसरे में बदला जा सकता है।

अंतराल के टाइप की जाँच is.period() आदि से की जा सकती है।

पीरियड

एक period, जैसे hours(3), किसी घड़ी के समय को 3 घंटे बढ़ाने के लिए उपयोग किया जा सकता है।

डेलाइट सेविंग टाइम (DST) जैसी अनियमितताओं को अधिकतर अनदेखा किया जाता है।

सभी पीरियड किसी इकाई का बहुवचन नाम होते हैं: years, weeks, आदि।

d <- today()
d
#> [1] "2026-04-25"

d + weeks(2)
#> [1] "2026-05-09"

# dates are coerced to datetimes at midnight if necessary
d - hours(20)
#> [1] "2026-04-24 04:00:00 UTC"

hours(3)
#> [1] "3H 0M 0S"

ड्यूरेशन

एक duration, जैसे dhours(3), भौतिक समय को 3 घंटे बढ़ाता है और DST जैसी उन अनियमितताओं का ध्यान रखता है जिनके कारण घड़ी का समय भौतिक समय से हट जाता है।

सभी ड्यूरेशन अपने संबंधित पीरियड में d उपसर्ग जोड़ते हैं: dyears, dweeks, आदि।

dhours(3)
#> [1] "10800s (~3 hours)"

इंटरवल

एक interval शुरुआत और अंत के समय का जोड़ा होता है, जिसे या तो interval() फंक्शन से बनाया जाता है या %--% इन्फिक्स ऑपरेटर से।

# the next 2 lines were run about 33s apart, so now() is different
dt1 <- now()
dt2 <- now() + hours(1)

# interval(0 function)
ivl <- interval(dt1, dt2)
ivl
#> [1] 2026-04-24 16:24:54 MST--2026-04-24 17:25:27 MST

# infix operator
iv2 <- dt1 %--% dt2
iv2 == iv1
#> [1] TRUE

टाइमज़ोन

टाइमज़ोन से निपटना मुश्किल हो सकता है। नीचे दिया गया उद्धरण Python के डॉक्युमेंटेशन से है, लेकिन R के लिए भी उतना ही प्रासंगिक है:

"दुनिया भर में समय समायोजित करने के नियम तर्क से अधिक राजनीतिक होते हैं, बार-बार बदलते रहते हैं, और UTC के अलावा हर अनुप्रयोग के लिए उपयुक्त कोई मानक नहीं है।"

टाइमज़ोन के बारे में कुछ सामान्य बातें:

  • एक datetime में हमेशा एक टाइमज़ोन (tz) शामिल होता है; एक date टाइमज़ोन को नहीं जानती।
  • डेटटाइम कंस्ट्रक्टर आमतौर पर डिफ़ॉल्ट रूप से UTC लेते हैं।
  • now() फंक्शन एक अपवाद है: यह आपके सिस्टम क्लॉक से आपका स्थानीय समय लेता है, जिसमें tz भी शामिल होता है। डिफ़ॉल्ट रूप से स्थानीय tz उपयोग होता है, लेकिन now("UTC") जैसे अन्य भी दिए जा सकते हैं।
# timezone defaults to UTC
local <- ymd_hm("2026-04-25 10:32")
local
#> [1] "2026-04-25 10:32:00 UTC"

# timezone can be specified
AZ <- ymd_hm("2026-04-25 10:32", tz = "America/Phoenix")
AZ
#> [1] "2026-04-25 10:32:00 MST"

# same clocktime, different tz
local - AZ
#> Time difference of -7 hours

पीरियड के मुकाबले ड्यूरेशन के साथ टाइमज़ोन से जुड़ा गणित अधिक भरोसेमंद होता है।

निष्कर्ष

डेट और डेटटाइम के साथ काम करना आमतौर पर Base R की तुलना में lubridate के साथ बहुत आसान होता है।

इस कॉन्सेप्ट ने एक अवलोकन देने की कोशिश की है, लेकिन स्वाभाविक रूप से इसमें बहुत सारे विवरण छूट गए हैं।

दोहराने के जोखिम के साथ: डॉक्युमेंटेशन आपका मित्र है, इसलिए कृपया इसका उपयोग कीजिए।

निर्देश

इस अभ्यास में आप न्यू यॉर्क के एक ब्यूटी सैलून के लिए अपॉइंटमेंट शेड्यूलर पर काम करेंगे। यह सैलून 15 सितंबर 2012 को खुला था।

आपके पास पाँच कार्य हैं, और इन सभी में अपॉइंटमेंट की तारीखों से काम पड़ेगा। समय 24-घंटे की घड़ी के प्रारूप में है (AM/PM नहीं)। टाइमज़ोन से जुड़ी दिक्कतों को जितना आसान हो सके उतना आसान रखने के लिए, मान लीजिए कि सब कुछ UTC का उपयोग करता है।

1. अंकों वाली अपॉइंटमेंट तारीख को पढ़कर DateTime में बदलिए

schedule_appointment() फंक्शन बनाइए, जो अपॉइंटमेंट की तारीख के टेक्स्ट को पढ़कर उसे उससे मेल खाते DateTime प्रारूप में बदल देता है।

ध्यान दीजिए कि इनपुट अमेरिकी शैली के महीना/दिन/वर्ष क्रम में है।

julia> schedule_appointment("07/25/2023 13:45:00")
2023-07-25T13:45:00

2. जाँचिए कि अपॉइंटमेंट बीत चुका है या नहीं

has_passed() फंक्शन बनाइए, जो एक अपॉइंटमेंट की तारीख लेता है और जाँचता है कि अपॉइंटमेंट कहीं अतीत में था या नहीं:

julia> has_passed(DateTime(1999, 12, 31, 9, 0, 0))
true

3. जाँचिए कि अपॉइंटमेंट दोपहर में है या नहीं

is_afternoon_appointment() फंक्शन बनाइए, जो एक अपॉइंटमेंट की तारीख लेता है और जाँचता है कि अपॉइंटमेंट दोपहर में है या नहीं (>= 12:00 और < 18:00):

julia> is_afternoon_appointment(DateTime(2023, 3, 29, 15, 0, 0))
true

4. जाँचिए कि अपॉइंटमेंट सप्ताह के किस दिन है

day_of_week() फंक्शन बनाइए, जो सप्ताह के दिन को संख्या के रूप में लौटाता है। सैलून रविवार को बंद रहता है, इसलिए सोमवार दिन 1 है और शनिवार दिन 6।

# a Friday
day_of_week(make_datetime(2026, 06, 05, 12, 30, 00))
#> [1] 5

5. अपॉइंटमेंट का समय बदलिए

जब किसी ग्राहक को अपॉइंटमेंट का समय बदलवाना होता है, तो यह अपने आप अगले शुक्रवार को उसी समय पर तय कर दिया जाता है (क्योंकि यह सप्ताह का सबसे कम भीड़ वाला दिन है)।

reschedule() फंक्शन बनाइए, जो मूल अपॉइंटमेंट (महीना/दिन/वर्ष क्रम में लिखी टेक्स्ट स्ट्रिंग के रूप में) लेता है और उसके नए समय वाला अपॉइंटमेंट लौटाता है।

# a Saturday
reschedule("06/13/2026 12:30:00")
#> [1] "2026-06-19 12:30:00 UTC"

अगर मूल अपॉइंटमेंट सोमवार से गुरुवार के बीच था, तो उसे इसी सप्ताह के शुक्रवार पर ले जाइए। शुक्रवार या शनिवार के अपॉइंटमेंट के लिए, उसे अगले सप्ताह के शुक्रवार पर ले जाइए।

GitHub के ज़रिए संपादित करें यह लिंक एक नई विंडो या टैब में खुलता है
R Exercism

ब्यूटी के लिए बुकिंग शुरू करने के लिए तैयार हैं?

Exercism पर साइन अप कीजिए और R को 21 कॉन्सेप्ट111 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।