مهرداد
مهرداد
خواندن ۷ دقیقه·۳ سال پیش

کتابخانه جاوااسکریپت JSS-Date: معرفی


کتابخانه JSS-Date یک کتابخانه جاوااسکریپتی برای کار با تاریخ و زمان است. هدف از طراحی این کتابخانه، رفع کاستی‌های کتابخانه‌های موجود و پشتیبانی از تقویم‌هایی به غیر از تقویم میلادی (تقویم هجری قمری، هجری شمسی و غیره) است.

در مقاله قبلی، به اختصار وضعیت کتابخانه معروف moment.js را بررسی کردیم. از مشکلات کتابخانه moment.js می توان به موارد زیر اشاره کرد:

  • پشتیبانی ضعیف از تقویم هایی به غیر از تقویم میلادی
  • تغییر پذیر بودن اشیا (mutable بودن)
  • حجم نسبتا بالا
  • عدم پشتیبانی از Tree-Shaking
  • عدم پشتیبانی مناسب از Intl API

بعضی از کتابخانه‌های جاوااسکرپتی مانند کتابخانه Luxon بخشی از این مشکلات را رفع کرده‌اند اما همه آنها مبتنی بر تقویم میلادی هستند. کتابخانه JSS-Date با هدف رفع همه این کاستی‌ها طراحی و ساخته شده است. هنگام طراحی این کتابخانه، موارد زیر مد نظر قرار گرفته شده است:

  • پشتیبانی از تقویم‌هایی غیر از میلادی (شمسی، هجری قمری و غیره)
  • توسعه‌پذیر بودن (قابلیت ایجاد تقویم، Locale و پلاگین‌های جدید)
  • حجم کم
  • پشتیبانی از Tree-Shaking
  • طراحی Immutable و پیاده سازی API کلاس DateTime به صورت فلوئنت

نصب

کتابخانه JSS-Date در ریپازیتوری npm موجود است:

npm install @js-sugar/date --save

کتابخانه JSS-Date روی سرور (node.js) و همچنین مرورگر اجرا می‌شود.

پیکربندی پروژه

برای استفاده از این کتابخانه، ابتدا باید تقویم‌هایی که در پروژه نیاز دارید را import و معرفی کنید. این کار را در هنگام شروع پروژه (Startup) و برای یک بار انجام می‌دهیم.
این کتابخانه مستقل از تقویم طراحی شده است، به این معنا که هیچ تفاوتی بین تقویم میلادی و بقیه تقویم ها وجود ندارد. زمانی که یک شی DateTime ساخته می‌شود، پارامتر تقویم به سازنده آن شی داده می‌شود. در ادامه به نحوه ساخت اشیا تاریخ خواهیم پرداخت. فعلا فقط باید مشخص کنیم که در پروژه مان با چه تقویم هایی سر و کار داریم:

import { Calendars } from '@js-sugar/date'; import { GregorianCalendar } from '@js-sugar/date/calendars/gregorian'; import { PersianCalendar } from '@js-sugar/date/calendars/persian'; import { HijriCalendar } from '@js-sugar/date/calendars/hijri'; Calendars.add(new GregorianCalendar('gregorian')); Calendars.add(new PersianCalendar('persian')); Calendars.add(new HijriCalendar ('hijri'));

به ازای هر تقویم، یک کلاس مجزا وجود دارد. در اینجا کلاس‌های GregorianCalendar ،PersianCalendar و HijriCalendar را import کرده‌ایم. تنها کاری که باید انجام دهیم این است که از هر تقویم یک شی بسازیم و به مجموعه تقویم های پروژه ( کلاس Calendars) اضافه کنیم.
هر تقویم یک شناسه یکتا (ID) در سرتاسر پروژه دارد که در هنگام ساخت تقویم به سازنده (constructor) آن داده می‌شود. بعد از ساخت اشیا Calendar، آنها را به مجموعه تقویم های پروژه (کلاس Calendars) اضافه می‌کنیم. اولین تقویمی که به مجموعه Calendars اضافه می‌شود، تقویم پیش فرض پروژه خواهد بود.

همه تقویم‌ها از کلاس پایه Calendar به ارث می‌برند. شما به راحتی می‌توانید تقویم خودتان را پیاده سازی کنید فقط باید چند متد abstract را پیاده سازی کنید.

پیکربندی کتابخانه را تنها در هنگام startup پروژه انجام می‌دهیم. بعد از آن فقط به سادگی اشیا DateTime را تولید و استفاده می‌کنیم. اگر از فریم‌ورک‌های جاوااسکریپتی مانند Angular یا React استفاده می‌کنید، مطمئن شوید که کد مربوط به افزودن تقویم ها به کلاس Calendars فقط یک بار اجرا می‌شود.

در تمامی مثال‌های این مقاله فرض شده است که یک تقویم میلادی (با شناسه gregorian)، یک تقویم شمسی (با شناسه persian) و یک تقویم هجری قمری (با شناسه hijri) به پروژه اضافه شده است.

ایجاد شی DateTime

شی اصلی کتابخانه JSS-Date شی DateTime است. این شی مقدار تاریخ و زمان (با توجه به یک تقویم خاص) را در خود نگهداری می‌کند. شی DateTime به 3 پارامتر وابستگی دارد:

  • تقویم
    در هنگام ساخت شی DateTime می‌توانیم تقویم مورد استفاده را به عنوان یکی از پارامترهای سازنده (constructor) مشخص کنیم. اگر تقویم را مشخص نکنیم، تقویم پیش فرض پروژه به عنوان تقویم این شی منظور خواهد شد.
  • لوکل (Locale)
    زمانی که می‌خواهیم بخش‌هایی از یک تاریخ را به رشته تبدیل کنیم، باید زبان مورد استفاده را مشخص کنیم. مثلا اگر یک شی DateTime داشته باشید که تقویم آن هجری شمسی است و مقدار آن برابر 1400/2/27 است و می‌خواهید مقدار "ماه" این شی را به صورت رشته‌ای نمایش دهید، باید مشخص کنید که این نمایش در چه زبانی صورت گیرد. اگر زبان فارسی باشد، خروجی رشته "اردیبهشت" و اگر زبان انگلیسی باشد، خروجی رشته "Ordibehesht" خواهد بود. البته یک لوکل فقط شامل کلمات نیست، بلکه علائم و دیگر مشخصه‌های یک ناحیه جغرافیایی (معمولا یک کشور) را نیز شامل می‌شود.
    اگر هنگام ساخت یک DateTime لوکل را مشخص نکنیم، از لوکل پیشفرض پروژه استفاده خواهد شد.
  • منطقه زمانی (Time Zone)
    منطقه زمانی اختلاف ساعت شما با ساعت هماهنگ جهانی (UTC) را مشخص می‌کند. برای مثال منطقه زمانی Asia/Tehran یک اختلاف 3:30+ با UTC دارد.
    اگر هنگام ساخت یک DateTime منطقه زمانی را مشخص نکنیم، از منطقه زمانی سیستمی که برنامه روی آن اجرا می‌شود استفاده خواهد شد.
در هنگام ساخت یک شی DateTime، مقدار تقویم، لوکل و منطقه زمانی آن مشخص می‌شود (صراحتا و یا ضمنی) و بعد از آن به هیچ عنوان تغییر نمی‌کند. در واقع شی DateTime یک شی Immutable است و بعد از ساخته شدن، به هیچ عنوان تغییر نمی‌کند.

در ادامه با نحوه ایجاد و استفاده از اشیا DateTime آشنا خواهید شد.

مثال: ساخت یک DateTime که تقویم آن شمسی و مقدار آن برابر زمان جاری سیستم است:

import { DateTime } from '@js-sugar/date'; const pc = Calendars.find('persian'); // find a Calendar by its ID const d = new DateTime({calendar: pc}); console.log(d.year, d.month, d.day, d.hour, d.minute, d.second, d.ms); // output will be something like this: 1400, 5, 29, 12, 55, 50, 223

در مثال بالا، ابتدا تقویم فارسی را با متد find از مجموعه تقویم‌های پروژه جستجو کرده‌ایم و سپس آن را به سازنده کلاس DateTime داده‌ایم. یک راه ساده‌تر برای ساخت اشیا DateTime به صورت زیر است:

const d = new DateTime({calendar: 'persian'});

در کد بالا، شناسه (ID) تقویم را به صورت مستقیم به سازنده DateTime داده‌ایم. در این حالت، شی DateTime تقویم مربوطه را از میان تقویم‌های پروژه (Calendars) جستجو و پس از یافتن از آن استفاده خواهد کرد.

مثال: ساخت یک DateTime با تقویم شمسی و یک مقدار مشخص:

import { DateTime } from '@js-sugar/date'; const d = new DateTime({calendar: 'persian'}, 1400, 8, 21); console.log(d.year, d.month, d.day, d.hour, d.minute, d.second, d.ms); // output: 1400, 8, 21, 0, 0, 0, 0


مثال: ساخت یک DateTime با تقویم میلادی و یک مقدار مشخص:

import { DateTime } from '@js-sugar/date'; const d = new DateTime({calendar: 'gregorian'}, 2020, 10, 27); console.log(d.year, d.month, d.day); // output: 2020, 10, 27


مثال: ساخت یک DateTime با تقویم پیش فرض و زمان جاری سیستم:

import { DateTime } from '@js-sugar/date'; const d = new DateTime(); console.log(d.year, d.month, d.day); // The output depends on the default Calendar of the project


اولین تقویمی که به کلاس Calendars اضافه می‌شود، تقویم پیش فرض پروژه خواهد شد. اگر بعدا تصمیم به تغییر تقویم پیش‌فرض پروژه داشتید، به این روش می‌توانید تقویم پیش‌فرض را تغییر دهید:

import { Calendars } from '@js-sugar/ Calendars.default = Calendars.find('hijri');


سازنده کلاس DateTime

جهت سهولت ایجاد اشیا DateTime، سازنده این کلاس دارای چندین overload است:

DateTime(); DateTime(options); DateTime(year, month, day?, hour?, minute?, second?, ms?, options?); DateTime(options, year, month, day?, hour?, minute?, second?, ms?); DateTime(timestamp, options?);

پارامترهایی که اختیاری هستند با یک علامت سوال (?) مشخص شده‌اند. اگر پارامتری مشخص نشود، از مقادیر پیش‌فرض استفاده خواهد شد. مقدار پیش‌فرض برای پارامتر روز برابر 1 و برای پارامترهای ساعت، دقیقه، ثانیه و میلی ثانیه برابر 0 است.
پارامتر اختیاری options یک شی با سه فیلد اختیاری است:

{ calendar?: string | Calendar, locale?: string | Locale, zone?: string | Zone }

با استفاده از این پارامتر، می‌توانید تقویم، locale و zone شی DateTime را مشخص کنید. اگر این مقادیر را مشخص نکنید، از مقادیر پیش‌فرض استفاده خواهد شد.

  • اگر calendar را مشخص نکنید، از تقویم پیش‌فرض برنامه استفاده می‌شود. مقدار این پارامتر می‌تواند یک شی Calendar و یا یک رشته که مشخص کننده ID یک تقویم است باشد. اگر از ID یک تقویم استفاده می‌کنید، این تقویم باید قبلا به مجموعه تقویم‌های برنامه (کلاس Calendars) اضافه شده باشد.
  • اگر locale مقدار نداشته باشد، از locale پیش‌فرض استفاده می‌شود. locale پیش‌فرض برابر locale کامپیوتری است که برنامه را اجرا می‌کند، مگر اینکه شما آن را تغییر دهید. مقدار این پارامتر می‌تواند یک شی Locale و یا یک رشته که مشخص کننده نام یک locale است باشد.
  • اگر zone مقدار نداشته باشد، از zone سیستم استفاده می‌شود. مقدار این پارامتر می‌تواند یک شی Zone و یا یک رشته که مشخص کننده یک منطقه زمانی استاندارد (IANA) است باشد. لیست مناطق زمانی IANA را می‌توانید از سایت ویکیپدیا یا سایت IANA مشاهد کنید. برای مثال رشته "Asia/Tehran" یک منطقه زمانی IANA معتبر است.

مثال: ساخت یک شی DateTime با تقویم شمسی و locale فارسی

const d = new DateTime({calendar: 'persian', locale: 'fa-IR'}, 1400, 9, 2);


تبدیل تاریخ‌ها

تبدیل کردن یک DateTime به یک DateTime متناظر با آن ولی با تقویمی متفاوت، بسیار آسان است. برای این کار از متد to شی DateTime استفاده میکنیم.
متد to، یک شی Calendar و یا شناسه یک Calendar (که به مجموعه تقویم‌های پروژه اضافه شده است) را می‌گیرد و یک DateTime جدید و معادل با تقویم مورد نظر را ایجاد می‌کند.

مثال: تبدیل یک DateTime با تقویم میلادی به یک DateTime با تاریخ شمسی معادل با آن

const d1 = new DateTime({calendar: 'gregorian'}, 2021, 11, 25); const d2 = d1.to('persian'); // OR ==> d2 = d1.to(Calendars.find('persian')); console.log(d2.year, d2.month, d2.day); // output: 1400, 9, 4


مثال: تبدیل یک DateTime با تقویم شمسی به یک DateTime با تاریخ میلادی معادل با آن

const d1 = new DateTime({calendar: 'persian'}, 1400, 9, 4); const d2 = d1.to('gregorian'); // OR ==> d2 = d1.to(Calendars.find('gregorian')); console.log(d2.year, d2.month, d2.day); // output: 2021, 11, 25


پشتیبانی و گزارش خطا

برای گزارش باگ یا ثبت درخواست برای افزودن قابلیت جدید، به ریپازیتوری پروژه JSS-Date مراجعه کنید:
https://github.com/js-sugar/date

در مقاله‌های بعدی، شما را بیشتر با قابلیت‌های کتابخانه JSS-Date آشنا خواهیم کرد.



مقالاتی که تا کنون در رابطه با کتابخانه جاوااسکریپتی JSS-Date منتشر کرده ایم:



ریپازیتوری پروژه (جهت ثبت باگ و درخواست افزودن قابلیت‌های جدید):
https://github.com/js-sugar/date


مستندات پروژه:
https://js-sugar.github.io/date

javascriptdatetimecalendarlibrary
برنامه نویس و مشاور فریمورک انگولار
شاید از این پست‌ها خوشتان بیاید