زمان¶
اکنون میخواهیم یک ساعت دیجیتال بسازیم. (ساعت آنالوگ یک تمرین خواهد بود!)
تا اینجا روی دستورات تمرکز داشتیم. با نمونههای HTTP و مقدار تصادفی، به Elm دستور دادیم که کار خاصی را بلافاصله انجام دهد، اما این الگوی عجیبی برای یک ساعت است. ما همیشه میخواهیم زمان فعلی سیستم را بدانیم. اینجاست که مفهوم اشتراک وارد میشود!
با کلیک روی دکمه "ویرایش" شروع و کد برنامه را مطالعه کنید. اکنون روی دکمه ویرایش کلیک کنید!
تمام مفاهیم جدید از بسته elm/time
میآیند. بیایید این بخشها را بررسی کنیم!
Time.Posix
و Time.Zone
¶
برای کار با زمان در زبانهای برنامهنویسی، به سه مفهوم مختلف نیاز داریم:
-
زمان پازیکس — با زمان POSIX، مهم نیست کجا زندگی میکنید یا چه زمانی از سال است. این فقط تعداد ثانیههایی است که از یک لحظه دلخواه (در سال ۱۹۷۰) گذشته است. در هر جایی که بروید، زمان POSIX یکسان است.
-
زمان انسانی — این همان چیزی است که بر روی ساعت (۸ صبح) یا تقویم (۸ خرداد) میبینید. عالی! اما اگر تماس من در ساعت ۸ صبح در بوستون باشد، برای دوستم در ونکوور چه ساعتی است؟ اگر در ساعت ۸ صبح در توکیو باشد، آیا این همان روز در نیویورک است؟ (نه!) بنابراین بین منطقههای زمانی بر اساس مرزهای سیاسی در حال تغییر و استفاده نامنظم از ساعت تابستانی، زمان انسانی هرگز نباید در
Model
یا پایگاه داده ذخیره شود! این زمان، فقط برای نمایش است! -
منطقه زمانی — یک "منطقه زمانی" مجموعهای از دادهها است که به شما اجازه میدهد زمان POSIX را به زمان انسانی تبدیل کنید. این فقط
UTC-7
یاUTC+3
نیست! منطقههای زمانی بسیار پیچیدهتر از یک جابجایی ساده هستند! هر بار که فلوریدا بطور دایم به DST تغییر میکند یا ساموآ از UTC-11 به UTC+13 تغییر میکند، یک انسان بیچاره یادداشتی به پایگاه داده منطقه زمانی IANA اضافه میکند. آن پایگاه داده بر روی کامپیوتر بارگیری میشود و بین زمان POSIX و تمام موارد خاص در پایگاه داده، میتوانیم زمان انسانی را محاسبه کنیم!
بنابراین، برای نشان دادن زمان به انسان، باید همیشه Time.Posix
و Time.Zone
را بدانید. همین! تمام مطالبی که درباره "زمان انسانی" بیان شد، برای تابع view
است، نهModel
. در واقع، میتوانید این را در تابع view
ببینید:
view : Model -> Html Msg
view model =
let
hour = String.fromInt (Time.toHour model.zone model.time)
minute = String.fromInt (Time.toMinute model.zone model.time)
second = String.fromInt (Time.toSecond model.zone model.time)
in
h1 [] [ text (hour ++ ":" ++ minute ++ ":" ++ second) ]
تابع Time.toHour
آرگومانهای Time.Zone
و Time.Posix
را میگیرد و یک Int
از 0
تا 23
به ما برمیگرداند که نشان میدهد در منطقه زمانی شما چه ساعتی است. این الگو، برای دقیقه و ثانیه نیز تکرار میشود.
اطلاعات بیشتری درباره مدیریت زمان در فایل README بسته elm/time
وجود دارد. اگر با زمانبندی، تقویم و موارد مشابه کار میکنید، حتما قبل از انجام کارهای بیشتر با زمان، این فایل را بخوانید!
subscriptions
¶
خوب، حالا چگونه باید Time.Posix
را دریافت کنیم؟ با یک اشتراک!
برای این کار، از تابع Time.every
استفاده میکنیم:
این تابع دو آرگومان میگیرد:
- یک بازه زمانی به میلیثانیه؛
1000
میلیثانیه که به معنای هر ثانیه است. اما میتوانیم از60 * 1000
برای هر دقیقه یا5 * 60 * 1000
برای هر پنج دقیقه استفاده کنیم. - یک تابع که زمان فعلی را به یک
Msg
تبدیل میکند؛ زمان فعلی به یکTick time
برای تابعupdate
تبدیل میشود.
این الگوی پایه، برای هر اشتراکی بکار میرود. با پیکربندی یک مقدار، توصیف میکنید چگونه مقدار Msg
تولید شود. خیلی هم بد نیست!
Task.perform
¶
دریافت Time.Zone
کمی پیچیدهتر است. برنامه یک دستور به این شکل ایجاد کرد:
مطالعه مستندات ماژول Task
بهترین راه برای درک این خط است. مستندات، بطور خاص، برای توضیح مفاهیم جدید نوشته شدهاند و فکر میکنم بیان مجدد آن مفاهیم در این قسمت، خارج از موضوع برنامه باشد. نکته این است که به سیستم زمان اجرا دستور میدهیم تا Time.Zone
را در زمان اجرای کد، در اختیار ما بگذارد.