کتابخانهی استاندارد Elixir چهار ماژول مختلف برای کار با تاریخ و زمان ارائه میدهد که هرکدام «ساختار» مخصوص خود را دارند.
ماژول Date. یک ساختار Date را میتوان با «سیگیل» ~D ساخت.
~D[2021-01-01]
ماژول Time. یک ساختار Time را میتوان با «سیگیل» ~T ساخت.
~T[12:00:00]
ماژول NaiveDateTime برای تاریخوساعتهای بدون منطقهی زمانی. یک ساختار NaiveDateTime را میتوان با «سیگیل» ~N ساخت.
~N[2021-01-01 12:00:00]
ماژول DateTime برای تاریخوساعتهای دارای منطقهی زمانی. استفاده از این ماژول برای منطقههای زمانی غیر از UTC به یک وابستگی خارجی نیاز دارد: یک پایگاه دادهی منطقهی زمانی.
برای مقایسهی تاریخها یا زمانها با یکدیگر، در ماژول مربوطه به دنبال تابع compare یا diff بگردید. عملگرهای مقایسه مانند ==، > و < به نظر میرسد کار میکنند، اما مقایسهی معنایی درستی برای این ساختارها انجام نمیدهند.
دوستِ کتابدارتان از شما خواسته است که نرمافزار کتابخانهاش را گسترش دهید تا جریمههای دیرکرد را بهطور خودکار محاسبه کند. سیستم فعلی او تاریخ و ساعت دقیق امانت گرفتن یک کتاب را بهصورت یک رشتهی تاریخوزمان ISO8601 ذخیره میکند. او یک کتابخانهی محلی در شهری کوچک در غنا اداره میکند که از منطقهی زمانی GMT (UTC+۰) استفاده میکند، ساعت تابستانی ندارد و نیازی نیست نگران مناطق زمانی دیگر باشد.
تابع LibraryFees.datetime_from_string/1 را پیادهسازی کنید. این تابع باید یک رشتهی تاریخوزمان ISO8601 را بهعنوان آرگومان بگیرد و یک ساختار NaiveDateTime برگرداند.
LibraryFees.datetime_from_string("2021-01-01T13:30:45Z")
# => ~N[2021-01-01 13:30:45]
اگر کتابی پیش از ظهر امانت گرفته شده باشد، خواننده ۲۸ روز فرصت دارد آن را بازگرداند. اگر در ظهر یا بعد از آن امانت گرفته شده باشد، این مهلت ۲۹ روز است.
تابع LibraryFees.before_noon?/1 را پیادهسازی کنید. این تابع باید یک ساختار NaiveDateTime بگیرد و یک «مقدار منطقی» برگرداند.
LibraryFees.before_noon?(~N[2021-01-12 08:23:03])
# => true
بر اساس تاریخوزمان امانت، تاریخ بازگرداندن را محاسبه کنید.
تابع LibraryFees.return_date/1 را پیادهسازی کنید. این تابع باید یک ساختار NaiveDateTime بگیرد و یک ساختار Date برگرداند؛ یعنی ۲۸ یا ۲۹ روز بعد.
LibraryFees.return_date(~N[2020-11-28 15:55:33])
# => ~D[2020-12-27]
کتابخانه برای بازگرداندنهای دیرکرد نرخ ثابتی دارد. برای اینکه بتوانیم جریمه را محاسبه کنیم، باید بدانیم کتاب چند روز پس از تاریخ بازگرداندن، واقعاً بازگردانده شده است.
تابع LibraryFees.days_late/2 را پیادهسازی کنید. این تابع باید دو ورودی بگیرد: یک ساختار Date (تاریخ بازگرداندن برنامهریزیشده) و یک ساختار NaiveDateTime (تاریخوزمان واقعی بازگرداندن).
اگر تاریخ بازگرداندن واقعی، روزی پیشتر یا همان روزِ تاریخوزمان بازگرداندن برنامهریزیشده باشد، تابع باید ۰ برگرداند. در غیر این صورت، تابع باید تفاوت آن دو تاریخ را بر حسب روز برگرداند.
کتابخانه هم تاریخ و هم ساعت بازگرداندن واقعی کتاب را برای اهداف آماری ثبت میکند، اما هنگام محاسبهی جریمههای دیرکرد از ساعت استفاده نمیکند.
LibraryFees.days_late(~D[2020-12-27], ~N[2021-01-03 09:23:36])
# => 7
کتابخانه برای بازگرداندن کتابها در روزهای دوشنبه پیشنهاد ویژهای دارد.
تابع LibraryFees.monday?/1 را پیادهسازی کنید. این تابع باید یک ساختار NaiveDateTime بگیرد و یک مقدار منطقی برگرداند.
LibraryFees.monday?(~N[2021-01-03 13:30:45Z])
# => false
تابع LibraryFees.calculate_late_fee/3 را پیادهسازی کنید. این تابع باید سه آرگومان بگیرد: دو رشتهی تاریخوزمان ISO8601 (تاریخوزمان امانت و تاریخوزمان بازگرداندن واقعی) و جریمهی یک روز دیرکرد. این تابع باید جریمهی کل دیرکرد را بر اساس میزان دیرکرد در بازگرداندن واقعی کتاب برگرداند.
پیشنهاد ویژهی دوشنبه را هم در نظر بگیرید. اگر کتاب را روز دوشنبه بازگردانید، ۵۰٪ تخفیف میگیرید و مبلغ به پایین گرد میشود.
# Sunday, 7 days late
LibraryFees.calculate_late_fee("2020-11-28T15:55:33Z", "2021-01-03T13:30:45Z", 100)
# => 700
# one day later, Monday, 8 days late
LibraryFees.calculate_late_fee("2020-11-28T15:55:33Z", "2021-01-04T09:02:11Z", 100)
# => 400