مسیرها
/
Julia
Julia
/
تمرین‌ها
/
رزرو برای زیبایی
رزرو برای زیبایی

رزرو برای زیبایی

تمرین یادگیری

مقدمه

«تاریخ و زمان چیزی است که به کودکان خردسال یاد می‌دهیم. چقدر می‌تواند سخت باشد؟»

بسیاری از برنامه‌نویسان این اشتباه را مرتکب شده‌اند و تجربه‌ی پس از آن معمولاً تأثیر بدی بر سلامت و شادی‌شان می‌گذارد.

هر کسی که برنامه‌نویسی غیرساده با تاریخ و زمان انجام می‌دهد، دست‌کم باید آماده باشد مشکلات احتمالی را درک و آن‌ها را کاهش دهد.

این سند تلاش می‌کند نمای کلی‌ای از نحوه‌ی برخورد Julia با تاریخ و زمان ارائه دهد، اما برای جزئیات بیشتر مراجعه به راهنما ضروری خواهد بود. یک ویکی‌کتاب هم هست که بعضی خوانندگان ممکن است توضیحاتش را روشن‌تر بدانند و شامل یک نمودار مفید از سلسله‌مراتب نوع‌ها است.

ماژول Dates

بیشتر قابلیت‌های پایه در Dates قرار دارند؛ ماژولی که در نصب پیش‌فرض گنجانده شده اما بخشی از کتابخانه‌ی استاندارد نیست.

برای استفاده از این ماژول دو گزینه وجود دارد:

  1. import Dates را اضافه کنید و سپس پیش از همه‌ی فراخوانی‌های تابع Dates. بگذارید.
  2. using Dates را اضافه کنید که کل ماژول را به فضای نام جاری می‌آورد (به‌جز چند اسم مسئله‌دار).
# option 1
julia> import Dates

julia> Dates.now()
2025-06-21T16:02:39.080

julia> now()  # wrong: need to include `Dates.` after an import
ERROR: UndefVarError: `now` not defined in `Main`


# option 2
julia> using Dates

julia> now()  # functions are now in the namespace
2025-06-21T16:03:04.161

ماژول Dates بزرگ و پیچیده است، اما چهار نوع اصلی از قابلیت‌ها را فراهم می‌کند:

  • Dates.Date که شامل روز-ماه-سال است اما زمانِ روز را ندارد.
  • Dates.Time که شامل زمانِ روز است اما تاریخ ندارد.
  • Dates.DateTime که تاریخ و زمان را با هم ترکیب می‌کند.
  • Dates.Period که بازه‌های زمانی/تاریخی را مدیریت می‌کند.

توجه داشته باشید که یک DateTime عموماً اطلاعات منطقه‌ی زمانی را شامل نمی‌شود (Python به این نوع، datetime «ساده» می‌گوید). یک استثنا now() است که زمان محلی را از ساعت سیستم شما می‌گیرد و در صورت نیاز می‌تواند آن را به UTC تبدیل کند.

شاید رایج‌ترین نیازها این‌ها باشند:

  • تجزیه‌ی یک قالب ورودی مناسب برای ساختن یک نوع Dates.
  • گرفتن قالب عددی یا رشته‌ای مورد نیاز از یک نوع Dates.
  • اعمال یک آفست به یک مقدار Date، Time یا DateTime.
  • محاسبه‌ی بازه‌ی میان دو مقدار از این نوع.
  • گرفتن تاریخ جاری (با today()) و/یا زمان (با now()).
Note

برای کاهش حواس‌پرتی بصری، بیشتر کدهای نمونه در ادامه‌ی این سند فرض می‌کنند که using Dates انجام شده و از آوردن نام ماژول Dates. در فراخوانی‌های تابع پرهیز می‌کنند.

قالب‌های تاریخ و زمان

راه‌های بسیاری برای نوشتن تاریخ و زمان وجود دارد که معمولاً وابسته به فرهنگ‌اند. تاریخ‌هایی که کاملاً عددی‌اند، مانند «7/6/23»، مبهم و گیج‌کننده‌اند و به اشتباهات پرهزینه‌ی زیادی در سازمان‌های چندملیتی منجر شده‌اند (نویسنده این را از تجربه‌ی تلخ شخصی می‌گوید).

استاندارد بین‌المللی در ISO 8601 تعریف شده است و دو مزیت اصلی دارد:

  • تجزیه سریع و بدون ابهام است.
  • مرتب‌سازی آسان است، زیرا می‌توان با تاریخ‌وزمان مانند متن معمولی رفتار کرد و آن را به ترتیب الفبایی مرتب کرد.

در مثال قبلی دیدیم که Date.now() مقدار 2025-06-21T16:03:04.161 را برگرداند.

این مقدار از بخش‌های مختلفی ساخته می‌شود:

  • YYYY-MM-DD برای بخش تاریخ.
  • hh:mm:ss برای بخش زمان.
  • به‌صورت اختیاری، میلی‌ثانیه (یا واحد حتی کوچک‌تر) پس از نقطه‌ی اعشار.

قالب‌های رشته‌ای دیگر در بخش بعدی بحث خواهند شد.

تاریخ

Dates.Date یک نوع نسبتاً ساده و تنها-تاریخی است که هیچ درکی از زمان‌ها یا منطقه‌های زمانی ندارد.

# constructor with year, month, day arguments
julia> date1 = Date(2025, 06, 23)
2025-06-23

# constructor with ISO 8601 string
julia> date2 = Date("2025-06-23")
2025-06-23

julia> date1 == date2
true

julia> typeof(date1)
Date

توابع دسترسی‌دهنده برای بخش‌های جداگانه‌ی تاریخ وجود دارند و این‌ها به‌صورت جفت‌هایی هستند که با بزرگ یا کوچک بودن حرف از هم متمایز می‌شوند.

# lowercase returns an integer
julia> month(date1)
6

julia> typeof(month(date1))
Int64

# Propercase returns a Period type
julia> Month(date1)
6 months

julia> typeof(Month(date1))
Month

توابع پرس‌وجو

انواع مختلفی از توابع وجود دارند که درکی از تقویم دارند. مثال بعدی فقط چند مورد را نشان می‌دهد.

julia> date1
2025-06-23

julia> dayofweek(date1) # 1 = Monday, 7 = Sunday
1

julia> dayname(date1)
"Monday"

julia> daysinmonth(date1)
30

julia> isleapyear(date1)
false

julia> lastdayofmonth(date1)
2025-06-30

زمان

Dates.Time نوع پایه و تنها-زمانی است. هیچ درکی از تاریخ ندارد: زمان‌ها در نیمه‌شب به‌طور خودکار به Time(0, 0, 0) برمی‌گردند.

قالب کامل سازنده Time(hour, min, sec, millisec, microsec) یا معادل ISO 8601 آن است.

همه‌ی پارامترها اختیاری‌اند و به‌طور پیش‌فرض 0 خواهند بود.

julia> Time(14, 57, 25, 142)
14:57:25.142

julia> Time("14:57:25.142")
14:57:25.142

julia> Time(14, 57, 25, 142, 32)
14:57:25.142032

مانند Date، بخش‌های جداگانه با توابع دسترسی‌دهنده در دسترس هستند:

julia> minute(t) # => integer
57

julia> Minute(t) # => Period
57 minutes

تاریخ‌وزمان

Dates.DateTime بیشتر ویژگی‌های نوع‌های Date و Time را با هم ترکیب می‌کند.

julia> dt1 = DateTime(2025, 6, 23, 14, 57, 25, 142)
2025-06-23T14:57:25.142

# date1 and t were defined in previous examples
julia> dt2 = DateTime(date1, t)
2025-06-23T14:57:25.142

پارامترهای سال، ماه و روز به‌طور پیش‌فرض 1 هستند و همه‌ی پارامترهای زمان به‌طور پیش‌فرض 0.

به خاطر سپردن ترتیب درست همه‌ی این پارامترها می‌تواند چالش‌برانگیز باشد، بنابراین قالب ISO ممکن است برای ورودی ترجیح داده شود.

به‌طور جایگزین، می‌توان یک DateTime را از یک Date و یک Time ساخت، همان‌طور که در مثال بالا آمد.

بازه

هر یک از اجزای تاریخ/زمان نوع Period مخصوص خود را دارد، از Year تا Nanosecond، که بازه‌ای از زمان را نمایش می‌دهد. این‌ها به‌ویژه برای محاسبات حسابی مفیدند.

julia> dt1
2025-06-23T14:57:25.142

julia> Year(21)
21 years

julia> Second(61)
61 seconds

julia> dt1 + Year(21) - Second(61)
2046-06-23T14:56:24.142

julia> Date(2025, 07, 03) - Date(2025, 04, 25)
69 days

هنگام کار با نوع‌های Period، Julia تلاش می‌کند درباره‌ی بی‌نظمی‌های تقویمی مانند طول ماه هوشمندانه عمل کند و در صورت لزوم گرد می‌کند.

# February has fewer days than January
julia> Date(2025, 1, 31) + Month(1) 
2025-02-28

نمایش‌های رشته‌ای

پیش‌تر به استاندارد ISO 8601 اشاره کردیم که نمایش پیش‌فرض تاریخ/زمان در Julia هنگام قالب‌بندی یا تجزیه‌ی رشته‌ها است.

بدیهی است که قالب‌های بسیار دیگری نیز به‌طور مکرر و اغلب به شیوه‌های وابسته به فرهنگ استفاده می‌شوند. برای رسیدگی به این‌ها، Julia نوع DateFormat را دارد که می‌توان آن را از یک رشته‌ی قالب با هر پیچیدگی دلخواه ساخت.

# dateformat"" string syntax
julia> dtfmt = dateformat"d/m/y"
dateformat"d/m/y"

julia> typeof(dtfmt)
DateFormat{Symbol("d/m/y"), Tuple{Dates.DatePart{'d'}, Dates.Delim{Char, 1}, Dates.DatePart{'m'}, Dates.Delim{Char, 1}, Dates.DatePart{'y'}}}

# DateFormat constructor
julia> DateFormat("d/m/y")
dateformat"d/m/y"

مثال بالا بسیار ساده است، فقط یک تاریخ در قالب روز/ماه/سال که در اروپا رایج است. دو گونه از نحوه‌ی نگارش نشان داده شده است، اما نتیجه یکسان است.

سپس می‌توان از یک DateFormat برای تجزیه‌ی هر رشته‌ی مناسبی استفاده کرد:

julia> DateTime("14/7/2023", dtfmt)
2023-07-14T00:00:00

ساختن یک DateFormat سربار قابل‌توجهی دارد، بنابراین انجام این کار فقط یک بار (همان‌طور که اینجا با dtfmt انجام شد) هنگام حلقه زدن روی رشته‌های تاریخ/زمانِ زیاد برای کارایی مفید است.

قالب‌ها می‌توانند بسیار پیچیده‌تر از این باشند، بنابراین برای جزئیات به راهنما مراجعه کنید.

از همان DateFormat می‌توان برای خروجی دادن یک تاریخ/زمان در هر قالب رشته‌ای دلخواه، با استفاده از تابع Dates.format() استفاده کرد.

متأسفانه به نظر می‌رسد تعارضی در فضای نام با format وجود دارد (دست‌کم تا Julia 1.11.5)، بنابراین بهتر است حتی پس از using Dates پیشوند Dates. را بگذارید.

julia> dt1
2025-06-23T14:57:25.142

julia> Dates.format(dt1, dateformat"e, u d")
"Mon, Jun 23"

همان‌طور که مستند شده است، "e, u d" نمایش متنی مختصر برای روز هفته و ماه را می‌دهد.

نمایش متنی به‌طور پیش‌فرض انگلیسی است. زبان‌های دیگر می‌توانند اضافه شوند، هرچند پشتیبانی از این کار در حال حاضر چندان مطلوب نیست.

دستورالعمل‌ها

در این تمرین شما روی یک برنامه‌ریز قرار ملاقات برای یک سالن زیبایی در نیویورک کار خواهید کرد که در ۱۵ سپتامبر ۲۰۱۲ افتتاح شد.

شما پنج تسک دارید که همه‌ی آن‌ها به تاریخ‌های قرار ملاقات مربوط می‌شوند. زمان‌ها در قالب ۲۴ ساعته هستند (بدون ق.ظ/ب.ظ).

1. تاریخ قرار ملاقات تمام‌عددی را تجزیه کنید

تابع 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() را پیاده‌سازی کنید که یک تاریخ قرار ملاقات می‌گیرد و بررسی می‌کند که آیا قرار ملاقات در بعدازظهر است (>= ۱۲:۰۰ و < ۱۸:۰۰):

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

4. زمان و تاریخ قرار ملاقات را توصیف کنید

تابع description() را پیاده‌سازی کنید که یک تاریخ قرار ملاقات می‌گیرد و توصیفی از آن تاریخ و زمان برمی‌گرداند:

julia> describe(DateTime(2023, 3, 29, 15, 0, 0))
"You have an appointment on Wednesday, March 29, 2023 at 15:00"

5. تاریخ سالگرد را برگردانید

تابع anniversary_date() را پیاده‌سازی کنید که تاریخ سالگرد امسال را برمی‌گرداند، که ۱۵ سپتامبر است:

julia> anniversary_date()  # run during 2025
2025-09-15
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Julia Exercism

آماده‌اید رزرو برای زیبایی را شروع کنید؟

در Exercism ثبت‌نام کنید تا Julia را همراه با 35 مفهوم128 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.