یکی از انواع فیلدهایی که در سیستم مدیریت فرایندها استفاده می شود، فیلدهای با محتوای تاریخ است که به دلیل ماهیت خاص خود چالشهایی را به همراه دارد . این چالشها بخصوص در هنگام استفاده از توابع برنامه نویسی پررنگ تر می شود. در این مطلب سعی می کنیم با ذکر مثالهای واقعی و کاربردی به انواع تعاملها و پردازشهای مرتبط با فیلدهای تاریخ بپردازیم تا بتوانیم در حد امکان جوابگوی ابهامها و سوالها در این زمینه باشیم. در ادامه ابتدا به مفهوم و ماهیت فیلد تاریخ و استانداردهای مختلف آن می پردازیم و سپس انواع پردازشهای مرتبط با فیلدهای تاریخی از مقداردهی تا مقایسه، جستجو و ... را توضیح می دهیم.
سیستم های مختلف تاریخ
هر یک از فرهنگها و ملل مختلف در دنیا، یک سیستم تاریخ مختص به خود را دارند. به این شکل که یک واقعه تاریخی (میلاد مسیح، هجرت پیامبر و ...) را به عنوان مبدا انتخاب کرده و تاریخهای خود را نسبت به این مبدا محاسبه می کنند. به این ترتیب، استانداردهای مختلفی تحت عنوان تاریخ میلادی، هجری شمسی، هجری قمری، عبری، چینی و ... برای تاریخ استفاده می شود. بدیهی است که تاریخ با این تنوع و تعدد استانداردها انمی تواند در محیطهای برنامه نویسی استفاده شود. بنابراین متخصصین و طراحان نرم افزار، سیستم یکدستی را پیاده سازی کرده اند که از این همه تشتت و چندگونگی تاریخها جلوگیری می کند.
مفهوم و استاندارد تاریخ در سیستمهای نرم افزاری
در پایگاه داده های مختلف، یک تاریخ واحد را به عنوان مبدا در نظر گرفته می شود و زمان سپری شده از آن تاریخ با یک استاندارد خاص ذخیره می شود. از طرفی سیستم مدیریت فرایندها با استفاده از پلتفرم برنامه نویسی javascript این قابلیت را دارد که این استاندارد را بصورت یک عدد صحیح با واحد میلی ثانیه نمایش دهد. مبدا تاریخی javascript اول ژانویه 1970 میلادی است یعنی این که هر تاریخ براساس مقدار خالص زمان سپری شده از مبدا (ساعت 24 - 1/1/1970) بر حسب میلی ثانیه محاسبه می گردد.
مثال: برای نمونه تاریخ 24-01-2023 را در نظر بگیرید.
در محیط javascript می توانیم با استفاده از متد Date.parse مقدار خالص این تاریخ را بدست آوریم:
; let pureDate=Date.parse(“2023, 01, 24" )
در این صورت مقدار pureDate برابر با 1674505800000 میلی ثانیه خواهد بود.
نمایش فیلدهای تاریخی
تا اینجا مشخص شد که محتوای فیلد تاریخ یک عدد صحیح و واحد آن میلی ثانیه است اما نمایش این عدد می تواند به فرمهای مختلف تاریخی مثل هجری، میلادی و ... باشد. برای این کار در سیستمهای مختلف، توابع مبدل (Convertor) نوشته شده که فرمتهای مختلف تاریخ را تولید می کند و نمایش می دهد. برای مثال فرض کنید می خواهیم تاریخ متناظر با 1000000000000 میلی ثانیه چیست. به این منظور در محیط javascript می توانید با استفاده از تابع Date و به شکل زیر تاریخ میلادی متناظر با این مقدار را بدست بیاورید:
; const d= new Date (1000000000000 )
حال اگر این ثابت را نمایش دهیم به شکل زیر خواهد بود:
Sat Mar 03 1973 13:16:40 GMT+0330 (Iran Standard Time)
ملاحظه می کنید که این مقدار متناظر است با تاریخ شنبه سوم مارس سال 1973.
تا اینجا با مفهوم عام فیلد تاریخ در نرم افزارها آشنا شدیم و به دلیل اینکه سیستم مدیریت فرایندها از محیط برنامه نویسی javascript استفاده می کند. اشاره کوچکی به نحوه کار با این مفهوم در محیط javascript داشتیم. در ادامه با نحوه پردازش این فیلدها در سیستم مدیریت فرایندها آشنا خواهیم شد.
توضیح: محیط برنامه نویسی در سیستم مدیریت فرایندها، به دلیل استفاده از کلاسهای اختصاصی تعریف شده در این سیستم، کمی با محیط عادی javascript متفاوت است که در ادامه با ویژگیها و ابزارهای اختصاصی مدیریت فرایندها در این محیط آشنا خواهیم شد.
مقداردهی فیلدهای تاریخی در سیستم مدیریت فرایندها
مقداردهی فیلدهای تاریخ در فرمها
در فرمهای انجام وظیفه می توانیم به دو فرم هجری شمسی و میلادی تاریخها را وارد کنیم. برای این کار می توانیم هم به شکل دستی تاریخ مورد نظر خود را تایپ کنیم و هم می توانیم از ابزار تقویم (Date Picker)، تاریخ مورد نظر خود را انتخاب کنیم. برای مثال به فرم زیر توجه کنید:
در این فرم یک تاریخ مشابه به دو فرم هجری شمسی و میلادی وارد شده است.
مقدار ذخیره شده در پایگاه داده ها
یادآوری می شود که این تاریخ در هنگام ذخیره شدن، بطور اتوماتیک تبدیل به مقدار میلی ثانیه از مبدا تاریخ شده و در پایگاه ذخیره می شود. برای نمونه در اینجا از طریق یک تابع اجرایی به شکل زیر، مقدار ذخیره شده فیلدهای تاریخ سفارش فارسی و لاتین نمایش داده شده است:
با اجرای این تابع، مقادیر فیلدها به شکل زیر نمایش داده می شود:
ملاحظه می کنید که برای هر دو تاریخ میلادی و شمسی یک مقدار مشابه یعنی 1674592200000 ذخیره شده است.
مقداردهی فیلدهای تاریخ در برنامه
برای مقداردهی یک فیلد تاریخ در برنامه، باید حتما مقدار میلی ثانیه را مقداردهی کنید. برای مثال فرض کنید می خواهید تاریخ 2021-03-21را در فیلدهای تاریخ ذخیره کنید برای این کار باید همانند مثال زیر از متد parse استفاده کنید:
با اجرای این تابع، مقادیر فیلدها ذخیره شده و در فرم به شکل زیر نمایش داده می شود:
نکته ای که در اینجا باید به آن توجه کنید این است که در این مثال یک تاریخ به فرم میلادی در فیلد تاریخ مقداردهی شد. برای مقداردهی یک تاریخ هجری شمسی کار کمی متفاوت است که در ادامه توضیح داده می شود.
ذخیره یک تاریخ فارسی (هجری شمسی) از طریق برنامه
برای امکان مقداردهی یک تاریخ هجری شمسی (جلالی)، باید از متد EncodeJalaliDate از کلاس WorkDateUtils به شکل زیر استفاده کنید:
در این مثال می خواهیم فیلدهای تاریخ را با 9/2/1397 مقداردهی کنیم. در اینجا متد EncodeJalaliDate در پشت صحنه، دو کار را انجام می دهد، ابتدا تاریخ جلالی را به میلادی تبدیل می کند و سپس مقدار خالص میلی ثانیه این تاریخ را استخراج می کند. به نمایش این فیلدها در فرم توجه کنید:
بدیهی است در غیر این صورت اگر از روش قبلی استفاده کنیم، سیستم تاریخ 1397/2/9 را یک تاریخ میلادی در نظر می گیرد و فیلدها به شکل اشتباه مقداردهی خواهند شد.
مقایسه محتوای یک فیلد تاریخی با یک تاریخ خاص
مثال 1- مقایسه با تاریخ جاری: فرض کنید در یک گردش کار فروش کالاها، می خواهیم تاریخ سفارش را کنترل کنیم و اگر این تاریخ بزرگتر از تاریخ جاری بود، پیغام خطا نمایش دهیم. در اینجا لازم است همانند تابع اجرایی زیر، تاریخ جاری را با تاریخ ثبت سفارش مقایسه کنیم.
ملاحظه می کنید که در این مثال کافی است محتوای فیلد تاریخ را با استفاده از یک عملگر مقایسه ای (در اینجا عملگر بزرگتر <) با تاریخ جاری مقایسه کنید.
مثال 2- مقایسه با یک تاریخ دلخواه: فرض کنید در یک گردش کار خدمات پس از فروش، می خواهیم برای تمام مشتریانی که در یک بازه تاریخی خاص (جشنواره فروش) خرید کرده اند، بخشی از پرداخت را به عنوان تخفیف به مشتری برگردانیم. تابع اجرایی زیر نمونه ای از این مثال را نشان می دهد:
disStartDate: تاریخ شروع جشنواره
disEndDate: تاریخ پایان جشنواره
paid: وجه پرداختی
discount: مقدار تخفیف
در اینجا مشتریانی که از اول تیر تا 31 شهریور 1401 خرید کرده اند شامل تخفیف ده درصدی می شوند.
تمرین: اگر بازه تاریخی در این مثال به میلادی باشد آنگاه تابع اجرایی به چه شکل خواهد بود؟
مقایسه محتوای دو فیلد تاریخی
مثال: فرض کنید در یک گردش کار تامین نیروی انسانی می خواهیم تاریخ شروع به کار کارمند را با تاریخ درخواست استخدام او مقایسه کنیم و اگر کوچکتر از آن بود پیغام خطا نمایش دهیم. در این حالت کافی است همانند تابع اجرای زیر، محتوای دو فیلد را بصورت ساده با هم مقایسه کنید:
جستجوی کارها بر مبنای فیلد تاریخ از طریق برنامه (SearchWork)
مثال1 – جستجوی تاریخ میلادی: فرض کنید می خواهیم فهرست تمام کارهای گردش کار درخواست کالا را که تاریخ سفارش آنها سال جاری میلادی است جستجو کنیم. در این صورت باید همانند تابع اجرایی زیر عمل کنیم:
همانطور که ملاحظه می کنید، برای تاریخهای به فرم میلادی جستجو خیلی ساده است و کافی است فرمت رشته ای تاریخ مورد نظر خود را در Value درج کنید.
مثال 2- جستجوی تاریخ هجری شمسی: برای تاریخهای فارسی، کار کمی سخت تر است چون باید ابتدا تاریخ شمسی را به میلادی تبدیل کنید و سپس جستجو را انجام دهید. برای مثال در تابع اجرایی زیر، کارهای با تاریخ سفارش سال جاری (1401) جستجو می شود:
ملاحظه می کنید که ابتدا از طریق EncodeJalaiDate مقدار خالص تاریخ شمسی بدست می آید و سپس از طریق توابع getFullYear، getMonth و getDate مقادیر لاتین سال، ماه و روز تاریخ استخراج می شود و سپس با استفاده از این سه مقدار، رشته حرفی فرمت تاریخ به فرم میلادی تولید و در متغیر strDate قرار می گیرد و در نهایت مقدار این متغیر در Value قرار می گیرد.
توضیح: از آنجایی که این جستجو در نهایت در Sqlserver انجام می شود لذا برای جستجو باید حتما فرمت رشته ای تاریخ به میلادی تولید شود و جستجو برمبنای این فرمت انجام شود.
برای تفکر بیشتر: در این مثال آیا نمی توانیم معادل لاتین تاریخ شمسی را پیدا کنیم و جستجو کنیم؟ در این صورت چه نیازی به این توابع پیچیده برای استخراج معادل لاتین داریم؟
جستجوی (Query) فیلدهای تاریخی در پایگاههای SQL
مثال: فرض کنید در گردش کار مدیریت منابع انسانی می خواهیم اطلاعات پرسنلی را که در یک بازه تاریخی استخدام شده اند تهیه کنیم. اطلاعات پرسنلی در یک پایگاه بنام WageDB و در یک جدول بنام PersSpec نگهداری می شود. ضمنا اطلاعات بازه استخدام در دو فیلد تاریخ شروع (startDate) و تاریخ پایان (endDate) تعیین می شود. ابتدا برای پرهیز از تکرار، یک تابع برای تولید رشته حرفی به فرم میلادی می نویسیم و سپس از این تابع در تابع اجرایی اصلی استفاده می کنیم.
این تابع برای محاسبه رشته حرفی تاریخ میلادی نوشته شده است. هرگاه خواستید رشته حرفی تاریخ را تولید کنید می توانید این تابع را Call کنید. برای مثال در تابع اجرایی زیر، این تابع دو بار Call شده است.
در این تابع ابتدا محتوای دو فیلد تاریخی شروع و پایان بازه تاریخی توسط تابع NaturalForm به رشته حرفی میلادی تبدیل شده اند و سپس این دو رشته به شکل متغیر در WhereClause قید شده است. یادآوری می شود که برای Query تاریخ در Sqlserver باید حتما به شکل رشته حرفی میلادی باشد.
توضیح مهم: مواردی که در این مستند ذکر شد موارد کلی و کاربردی برای فیلدهای تاریخی است. اما باید توجه داشته باشید که مفهوم فیلدهای تاریخ و توابع Date در javascript بسیار پیچیده تر و گسترده تر از این است. بنابراین لازم است برای آشنایی کامل با این مفاهیم به منابع آموزشی دیگر مراجعه کنید.