Skip to content

Commit 34913bd

Browse files
committed
feat(service): add date command for Gregorian and Persian date handling
- Introduce `tehranZone` function: - Adjusts the current date and time to Tehran timezone (UTC+3:30) without considering daylight saving time. - Add `DateCommand` class: - Provides functionality to retrieve the current date in both Gregorian and Persian calendars. - `date` method: - Returns the formatted Gregorian and Persian dates by combining timezone adjustments and conversion logic. - Utilizes the `@Catch` decorator to handle potential runtime errors. - `formatGregorianDate` method: - Formats a `Date` object into a human-readable string (e.g., "Sunday, January 1, 2024, time: 12:00"). - Includes day names, month names, and padded hours and minutes. - `convertToPersianDate` method: - Converts a `Date` object into a Persian calendar format with day names and month names in Farsi. - Outputs in the format: `<day> <day_of_month> <month_name> <year> ساعت: <hours>:<minutes>`. - `toJalaali` method: - Implements a Gregorian-to-Jalaali (Persian calendar) conversion algorithm. - Calculates Persian year, month, and day based on the input Gregorian date. - Accounts for leap years and Persian calendar-specific calculations.
1 parent 2cb3de7 commit 34913bd

1 file changed

Lines changed: 84 additions & 0 deletions

File tree

src/bot/service/general/date.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { Context } from 'grammy';
2+
import { Catch } from '../../../decorators/Catch';
3+
export function tehranZone() {
4+
// Get current date and adjust to Tehran time zone
5+
const now = new Date();
6+
const utcTime = now.getTime() + now.getTimezoneOffset() * 60000;
7+
8+
// Tehran timezone offset in minutes (UTC+3:30)
9+
const tehranOffset = 3.5 * 60;
10+
11+
// Adjust time to Tehran timezone without considering DST
12+
return new Date(utcTime + tehranOffset * 60000);
13+
}
14+
export class DateCommand {
15+
@Catch()
16+
static async date(): Promise<{
17+
gregorianDate: string;
18+
persianDate: string;
19+
}> {
20+
const tehranTime = tehranZone();
21+
// Format Gregorian Date
22+
const gregorianDate = this.formatGregorianDate(tehranTime);
23+
// Convert to Persian Date
24+
const persianDate = this.convertToPersianDate(tehranTime);
25+
return {
26+
gregorianDate,
27+
persianDate,
28+
};
29+
}
30+
static formatGregorianDate(date: Date): string {
31+
const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
32+
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
33+
34+
const dayName = days[date.getDay()];
35+
const day = date.getDate();
36+
const monthName = months[date.getMonth()];
37+
const year = date.getFullYear();
38+
const hours = date.getHours().toString().padStart(2, '0');
39+
const minutes = date.getMinutes().toString().padStart(2, '0');
40+
41+
return `${dayName}, ${monthName} ${day}, ${year}, time: ${hours}:${minutes}`;
42+
}
43+
44+
static convertToPersianDate(date: Date): string {
45+
// Gy: Gregorian year
46+
// Gm: Gregorian month (1-12)
47+
// Gd: Gregorian day of the month (1-31)
48+
const persianDate = this.toJalaali(date.getFullYear(), date.getMonth() + 1, date.getDate());
49+
const persianDays = ['شنبه', 'یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چهارشنبه', 'پنج‌شنبه', 'جمعه'];
50+
51+
const persianMonths = ['فروردین', 'اردیبهشت', 'خرداد', 'تیر', 'مرداد', 'شهریور', 'مهر', 'آبان', 'آذر', 'دی', 'بهمن', 'اسفند'];
52+
const dayName = Number(date.getDay() + 1) >= 7 ? persianDays[date.getDay() - 6] : persianDays[date.getDay() + 1];
53+
const hours = date.getHours().toString().padStart(2, '0');
54+
const minutes = date.getMinutes().toString().padStart(2, '0');
55+
56+
return `${dayName} ${persianDate.jd} ${persianMonths[persianDate.jm - 1]} ${persianDate.jy} ساعت: ${hours}:${minutes}`;
57+
}
58+
59+
static toJalaali(gy: number, gm: number, gd: number) {
60+
const g_d_m = [0, 31, (gy % 4 === 0 && gy % 100 !== 0) || gy % 400 === 0 ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
61+
let gy2 = gm > 2 ? gy + 1 : gy;
62+
let days = 355666 + 365 * gy + Math.floor((gy2 + 3) / 4) - Math.floor((gy2 + 99) / 100) + Math.floor((gy2 + 399) / 400) + gd;
63+
64+
for (let i = 0; i < gm; ++i) days += g_d_m[i];
65+
66+
let jy = -1595 + 33 * Math.floor(days / 12053);
67+
days %= 12053;
68+
69+
jy += 4 * Math.floor(days / 1461);
70+
days %= 1461;
71+
72+
if (days > 365) {
73+
jy += Math.floor((days - 1) / 365);
74+
days = (days - 1) % 365;
75+
}
76+
77+
// Month Calculation
78+
const jm = days < 186 ? 1 + Math.floor(days / 31) : 7 + Math.floor((days - 186) / 30);
79+
80+
// Day Calculation
81+
const jd = days < 186 ? days % 31 : (days - 186) % 30;
82+
return { jy, jm, jd };
83+
}
84+
}

0 commit comments

Comments
 (0)