diff --git a/sources/CONTRIBUTION.md b/sources/CONTRIBUTION.md new file mode 100644 index 0000000..73f867e --- /dev/null +++ b/sources/CONTRIBUTION.md @@ -0,0 +1,4 @@ +# Contribution Guide + +It is suggested for the new contributors to use the following tools: +- `clang-format` for all the C files, source and headers. diff --git a/sources/libjalali/jalali.c b/sources/libjalali/jalali.c index cfb2bf4..a531514 100644 --- a/sources/libjalali/jalali.c +++ b/sources/libjalali/jalali.c @@ -19,12 +19,13 @@ * along with libjalali. If not, see . */ -#include #include #include -#include +#include #include #include +#include + #include "jalali.h" #include "jconfig.h" @@ -34,22 +35,24 @@ * - new lo will be in [0, factor) * - new hi will be hi + lo / factor */ -#define RECLUSTER(hi, lo, factor) \ - if (lo < 0 || lo >= (factor)) {\ - hi += lo / (factor);\ - lo = lo % (factor);\ - if (lo < 0) { lo += (factor); hi--; }\ - } +#define RECLUSTER(hi, lo, factor) \ + if (lo < 0 || lo >= (factor)) { \ + hi += lo / (factor); \ + lo = lo % (factor); \ + if (lo < 0) { \ + lo += (factor); \ + hi--; \ + } \ + } -const int cycle_patterns[] = { J_PT0, J_PT1, J_PT2, J_PT3, INT_MAX }; -const int leaps[] = { J_L0, J_L1, J_L2, J_L3, INT_MAX }; +const int cycle_patterns[] = {J_PT0, J_PT1, J_PT2, J_PT3, INT_MAX}; +const int leaps[] = {J_L0, J_L1, J_L2, J_L3, INT_MAX}; -const int jalali_month_len[] = { 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, - 30, 29 }; -const int accumulated_jalali_month_len[] = { 0, 31, 62, 93, 124, 155, 186, - 216, 246, 276, 306, 336 }; +const int jalali_month_len[] = {31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29}; +const int accumulated_jalali_month_len[] = {0, 31, 62, 93, 124, 155, + 186, 216, 246, 276, 306, 336}; -extern char* tzname[2]; +extern char *tzname[2]; /* * Jalali leap year indication function. The algorithm used here @@ -61,149 +64,137 @@ extern char* tzname[2]; * The current 2820 year period started in the year AP 475 (AD 1096). */ -int jalali_is_jleap(int year) -{ - - /* Leap years from 1200 to 1299 AP */ - int leap1200[100] = { - [10] = 1, [14] = 1, [18] = 1, [22] = 1, [26] = 1, [30] = 1, - [34] = 1, [38] = 1, [43] = 1, [47] = 1, [51] = 1, [55] = 1, - [59] = 1, [63] = 1, [67] = 1, [71] = 1, [76] = 1, [80] = 1, - [84] = 1, [88] = 1, [92] = 1, [96] = 1 - }; - - /* Leap years from 1300 to 1399 AP */ - int leap1300[100] = { - [0] = 1, [4] = 1, [9] = 1, [13] = 1, [17] = 1, [21] = 1, - [25] = 1, [29] = 1, [33] = 1, [37] = 1, [42] = 1, [46] = 1, - [50] = 1, [54] = 1, [58] = 1, [62] = 1, [66] = 1, [70] = 1, - [75] = 1, [79] = 1, [83] = 1, [87] = 1, [91] = 1, [95] = 1, - [99] = 1 - }; - - /* Leap years from 1400 to 1499 AP */ - int leap1400[100] = { - [3] = 1, [8] = 1, [12] = 1, [16] = 1, [20] = 1, [24] = 1, - [28] = 1, [32] = 1, [36] = 1, [41] = 1, [45] = 1, [49] = 1, - [53] = 1, [57] = 1, [61] = 1, [65] = 1, [69] = 1, [74] = 1, - [78] = 1, [82] = 1, [86] = 1, [90] = 1, [94] = 1 - }; - - int i = year % 100; - - if(year >= 1200 && year <= 1299) { - if(leap1200[i] == 1) - return 1; - else - return 0; - } else if(year >= 1300 && year <= 1399) { - if(leap1300[i] == 1) - return 1; - else - return 0; - } else if(year >= 1400 && year <= 1499) { - if(leap1400[i] == 1) - return 1; - else - return 0; - } - - /* Keeping the old algorithm as fallback */ - - int pr = year; - - /* Shifting ``year'' with 2820 year period epoch. */ - pr -= JALALI_LEAP_BASE; - - pr %= JALALI_LEAP_PERIOD; - - /* - * According to C99 standards, modulo operator's result has the same sign - * as dividend. Since what we require to process has to be in range - * 0-2819, we have to shift the remainder to be positive if dividend is - * negative. - */ - if (pr < 0) { - pr += JALALI_LEAP_PERIOD; +int jalali_is_jleap(int year) { + + /* Leap years from 1200 to 1299 AP */ + int leap1200[100] = { + [10] = 1, [14] = 1, [18] = 1, [22] = 1, [26] = 1, [30] = 1, + [34] = 1, [38] = 1, [43] = 1, [47] = 1, [51] = 1, [55] = 1, + [59] = 1, [63] = 1, [67] = 1, [71] = 1, [76] = 1, [80] = 1, + [84] = 1, [88] = 1, [92] = 1, [96] = 1}; + + /* Leap years from 1300 to 1399 AP */ + int leap1300[100] = { + [0] = 1, [4] = 1, [9] = 1, [13] = 1, [17] = 1, [21] = 1, [25] = 1, + [29] = 1, [33] = 1, [37] = 1, [42] = 1, [46] = 1, [50] = 1, [54] = 1, + [58] = 1, [62] = 1, [66] = 1, [70] = 1, [75] = 1, [79] = 1, [83] = 1, + [87] = 1, [91] = 1, [95] = 1, [99] = 1}; + + /* Leap years from 1400 to 1499 AP */ + int leap1400[100] = { + [3] = 1, [8] = 1, [12] = 1, [16] = 1, [20] = 1, [24] = 1, + [28] = 1, [32] = 1, [36] = 1, [41] = 1, [45] = 1, [49] = 1, + [53] = 1, [57] = 1, [61] = 1, [65] = 1, [69] = 1, [74] = 1, + [78] = 1, [82] = 1, [86] = 1, [90] = 1, [94] = 1}; + + int i = year % 100; + + if (year >= 1200 && year <= 1299) { + if (leap1200[i] == 1) + return 1; + else + return 0; + } else if (year >= 1300 && year <= 1399) { + if (leap1300[i] == 1) + return 1; + else + return 0; + } else if (year >= 1400 && year <= 1499) { + if (leap1400[i] == 1) + return 1; + else + return 0; + } + + /* Keeping the old algorithm as fallback */ + + int pr = year; + + /* Shifting ``year'' with 2820 year period epoch. */ + pr -= JALALI_LEAP_BASE; + + pr %= JALALI_LEAP_PERIOD; + + /* + * According to C99 standards, modulo operator's result has the same sign + * as dividend. Since what we require to process has to be in range + * 0-2819, we have to shift the remainder to be positive if dividend is + * negative. + */ + if (pr < 0) { + pr += JALALI_LEAP_PERIOD; + } + + /* + * Every cycle consists of one 29 year period and three identical 33 year + * periods forming a 128 years length cycle. An exception applies to the + * last cycle being 132 years instead and it's last 33 years long partition + * will be extended for an extra 4 years thus becoming 37 years long. + * JALALI_LAST_CYCLE_START literally marks the beginning of this last + * cycle. + */ + + pr = (pr > JALALI_LAST_CYCLE_START) ? (pr - JALALI_LAST_CYCLE_START) + : pr % JALALI_NORMAL_CYCLE_LENGTH; + + /* + * Classifying year in a cycle. Assigning to one of the four partitions. + */ + + for (i = 0; i < J_LI; i++) { + if ((pr >= cycle_patterns[i]) && (pr < cycle_patterns[i + 1])) { + pr -= cycle_patterns[i]; + /* Handling year-0 exception */ + if (!pr) /* pr is zero */ + return 0; + /* + * If year is a multiple of four then it's leap, + * ordinary otherwise. + */ + else + return !(pr % J_LI); } + } - /* - * Every cycle consists of one 29 year period and three identical 33 year - * periods forming a 128 years length cycle. An exception applies to the - * last cycle being 132 years instead and it's last 33 years long partition - * will be extended for an extra 4 years thus becoming 37 years long. - * JALALI_LAST_CYCLE_START literally marks the beginning of this last - * cycle. - */ - - pr = (pr > JALALI_LAST_CYCLE_START) ? - (pr - JALALI_LAST_CYCLE_START) : pr % JALALI_NORMAL_CYCLE_LENGTH; - - /* - * Classifying year in a cycle. Assigning to one of the four partitions. - */ - - for (i=0; i= cycle_patterns[i]) && (pr < cycle_patterns[i+1])) - { - pr -= cycle_patterns[i]; - /* Handling year-0 exception */ - if (!pr) /* pr is zero */ - return 0; - /* - * If year is a multiple of four then it's leap, - * ordinary otherwise. - */ - else - return !(pr % J_LI); - } - } - - /* - * Our code flow better not reach this fail-safe - * return statement and I really mean it. - */ - return 0; + /* + * Our code flow better not reach this fail-safe + * return statement and I really mean it. + */ + return 0; } /* * Creates absolute values for day, hour, minute and seconds from time_t. * Values are signed integers. */ -void jalali_create_time_from_secs(time_t t, struct ab_jtm* d) -{ - d->ab_days = (t >= 0) ? (t / (time_t) J_DAY_LENGTH_IN_SECONDS) : - ((t - (time_t) J_DAY_LENGTH_IN_SECONDS + (time_t) 1) / - (time_t) J_DAY_LENGTH_IN_SECONDS); - - if (t >= 0) { - t %= (time_t) J_DAY_LENGTH_IN_SECONDS; - } - else { - t = (J_DAY_LENGTH_IN_SECONDS - - (abs(t - J_DAY_LENGTH_IN_SECONDS) % - J_DAY_LENGTH_IN_SECONDS)) % - J_DAY_LENGTH_IN_SECONDS; - } - - d->ab_hour = t / J_HOUR_LENGTH_IN_SECONDS; - t %= J_HOUR_LENGTH_IN_SECONDS; - d->ab_min = t / J_MINUTE_LENGTH_IN_SECONDS; - d->ab_sec = t % J_MINUTE_LENGTH_IN_SECONDS; +void jalali_create_time_from_secs(time_t t, struct ab_jtm *d) { + d->ab_days = (t >= 0) ? (t / (time_t)J_DAY_LENGTH_IN_SECONDS) + : ((t - (time_t)J_DAY_LENGTH_IN_SECONDS + (time_t)1) / + (time_t)J_DAY_LENGTH_IN_SECONDS); + + if (t >= 0) { + t %= (time_t)J_DAY_LENGTH_IN_SECONDS; + } else { + t = (J_DAY_LENGTH_IN_SECONDS - + (abs(t - J_DAY_LENGTH_IN_SECONDS) % J_DAY_LENGTH_IN_SECONDS)) % + J_DAY_LENGTH_IN_SECONDS; + } + + d->ab_hour = t / J_HOUR_LENGTH_IN_SECONDS; + t %= J_HOUR_LENGTH_IN_SECONDS; + d->ab_min = t / J_MINUTE_LENGTH_IN_SECONDS; + d->ab_sec = t % J_MINUTE_LENGTH_IN_SECONDS; } /* * Creates a timestamp from day, hour, minute and seconds. * Values are signed integers. */ -time_t jalali_create_secs_from_time(const struct ab_jtm* d) -{ - return (time_t) - ((time_t) d->ab_days * (time_t) J_DAY_LENGTH_IN_SECONDS + - (time_t) d->ab_hour * (time_t) J_HOUR_LENGTH_IN_SECONDS + - (time_t) d->ab_min * (time_t) J_MINUTE_LENGTH_IN_SECONDS + - (time_t) d->ab_sec); +time_t jalali_create_secs_from_time(const struct ab_jtm *d) { + return (time_t)((time_t)d->ab_days * (time_t)J_DAY_LENGTH_IN_SECONDS + + (time_t)d->ab_hour * (time_t)J_HOUR_LENGTH_IN_SECONDS + + (time_t)d->ab_min * (time_t)J_MINUTE_LENGTH_IN_SECONDS + + (time_t)d->ab_sec); } /* @@ -211,46 +202,44 @@ time_t jalali_create_secs_from_time(const struct ab_jtm* d) * Alters only tm_mday and tm_mon. * Zero on success, -1 on failure. */ -int jalali_create_date_from_days(struct jtm* j) -{ - int p = j->tm_yday; - if (p > 365 || p < 0) - return -1; - - p++; - int i; - - /* Traversing all twelve months, ranging from 0 to 11 */ - for (i=0; i<11; i++) { - if (p > jalali_month_len[i]) - p -= jalali_month_len[i]; - else - break; - } - - j->tm_mday = p; - j->tm_mon = i; - - return 0; +int jalali_create_date_from_days(struct jtm *j) { + int p = j->tm_yday; + if (p > 365 || p < 0) + return -1; + + p++; + int i; + + /* Traversing all twelve months, ranging from 0 to 11 */ + for (i = 0; i < 11; i++) { + if (p > jalali_month_len[i]) + p -= jalali_month_len[i]; + else + break; + } + + j->tm_mday = p; + j->tm_mon = i; + + return 0; } /* * Calculate day of year (0-365) based on month and day. */ -int jalali_create_days_from_date(struct jtm* j) -{ - int p; - if (j->tm_mon < 0 || j->tm_mon > 11) - return -1; +int jalali_create_days_from_date(struct jtm *j) { + int p; + if (j->tm_mon < 0 || j->tm_mon > 11) + return -1; - if (j->tm_mday < 1 || j->tm_mday > 31) - return -1; + if (j->tm_mday < 1 || j->tm_mday > 31) + return -1; - p = accumulated_jalali_month_len[j->tm_mon]; - p += j->tm_mday; - j->tm_yday = p - 1 /* zero based offset */; + p = accumulated_jalali_month_len[j->tm_mon]; + p += j->tm_mday; + j->tm_yday = p - 1 /* zero based offset */; - return 0; + return 0; } /* @@ -260,206 +249,201 @@ int jalali_create_days_from_date(struct jtm* j) * 3. Passed and remaining leap years in grand leap cycle. -pl, -rl * 4. Absolute passed leap years since grand leap cycle epoch (AP 475). -apl */ -void jalali_get_jyear_info(struct jyinfo* year) -{ - int y = year->y; - year->lf = jalali_is_jleap(year->y); - int i; - int d = (year->y >= JALALI_LEAP_BASE) ? 1 : -1; - int c = 0; - - for (i=JALALI_LEAP_BASE; ; i+=d) { - if (jalali_is_jleap(i)) { - c++; - } - - if (i == year->y) - break; +void jalali_get_jyear_info(struct jyinfo *year) { + int y = year->y; + year->lf = jalali_is_jleap(year->y); + int i; + int d = (year->y >= JALALI_LEAP_BASE) ? 1 : -1; + int c = 0; + + for (i = JALALI_LEAP_BASE;; i += d) { + if (jalali_is_jleap(i)) { + c++; } - year->apl = c * d; - year->pl = (d > 0) ? c % JALALI_TOTAL_LEAPS_IN_PERIOD : - JALALI_TOTAL_LEAPS_IN_PERIOD - (c % JALALI_TOTAL_LEAPS_IN_PERIOD); - year->rl = JALALI_TOTAL_LEAPS_IN_PERIOD - year->pl; + if (i == year->y) + break; + } - y-= JALALI_LEAP_BASE; - y%= JALALI_LEAP_PERIOD; - if (y < 0) - y+= JALALI_LEAP_PERIOD; + year->apl = c * d; + year->pl = (d > 0) ? c % JALALI_TOTAL_LEAPS_IN_PERIOD + : JALALI_TOTAL_LEAPS_IN_PERIOD - + (c % JALALI_TOTAL_LEAPS_IN_PERIOD); + year->rl = JALALI_TOTAL_LEAPS_IN_PERIOD - year->pl; - year->p = y; - year->r = JALALI_LEAP_PERIOD - y - 1; + y -= JALALI_LEAP_BASE; + y %= JALALI_LEAP_PERIOD; + if (y < 0) + y += JALALI_LEAP_PERIOD; - return ; + year->p = y; + year->r = JALALI_LEAP_PERIOD - y - 1; + + return; } /* * Calculates date (Jalali) based on difference factor from UTC Epoch by days. * 0 means 1 January 1970 (11 Dey 1348). */ -void jalali_get_date(int p, struct jtm* j) -{ - int porg = p; - time_t t; - struct tm lt; +void jalali_get_date(int p, struct jtm *j) { + int porg = p; + time_t t; + struct tm lt; #if defined _WIN32 || defined __MINGW32__ || defined __CYGWIN__ - struct timezone tz; - struct timeval tv; + struct timezone tz; + struct timeval tv; #endif - int wd = (p + J_UTC_EPOCH_WDAY) % J_WEEK_LENGTH; + int wd = (p + J_UTC_EPOCH_WDAY) % J_WEEK_LENGTH; - if (wd < 0) { - j->tm_wday = wd + J_WEEK_LENGTH; - } else { - j->tm_wday = wd; - } + if (wd < 0) { + j->tm_wday = wd + J_WEEK_LENGTH; + } else { + j->tm_wday = wd; + } - int y = J_UTC_EPOCH_YEAR, f=0; - p += J_UTC_EPOCH_DIFF; - int d; + int y = J_UTC_EPOCH_YEAR, f = 0; + p += J_UTC_EPOCH_DIFF; + int d; - while (1) { - d = (p >= 0) ? 1 : -1; - f = jalali_is_jleap(((d > 0) ? y : y-1)) ? - JALALI_LEAP_YEAR_LENGTH_IN_DAYS: - JALALI_NORMAL_YEAR_LENGTH_IN_DAYS; + while (1) { + d = (p >= 0) ? 1 : -1; + f = jalali_is_jleap(((d > 0) ? y : y - 1)) + ? JALALI_LEAP_YEAR_LENGTH_IN_DAYS + : JALALI_NORMAL_YEAR_LENGTH_IN_DAYS; - if ((0 <= p) && (p < f)) - break; + if ((0 <= p) && (p < f)) + break; - p-= (d * f); - y+= d; - } + p -= (d * f); + y += d; + } - j->tm_year = y; - j->tm_yday = p; + j->tm_year = y; + j->tm_yday = p; - jalali_create_date_from_days(j); - tzset(); - t = porg * J_DAY_LENGTH_IN_SECONDS; - localtime_r(&t, <); + jalali_create_date_from_days(j); + tzset(); + t = porg * J_DAY_LENGTH_IN_SECONDS; + localtime_r(&t, <); #if defined _WIN32 || defined __MINGW32__ || defined __CYGWIN__ - gettimeofday(&tv, &tz); - j->tm_gmtoff = (-tz.tz_minuteswest) * J_MINUTE_LENGTH_IN_SECONDS - + (tz.tz_dsttime * J_HOUR_LENGTH_IN_SECONDS); - j->tm_zone = tzname[lt.tm_isdst]; + gettimeofday(&tv, &tz); + j->tm_gmtoff = (-tz.tz_minuteswest) * J_MINUTE_LENGTH_IN_SECONDS + + (tz.tz_dsttime * J_HOUR_LENGTH_IN_SECONDS); + j->tm_zone = tzname[lt.tm_isdst]; #else - j->tm_gmtoff = lt.tm_gmtoff; - j->tm_zone = lt.tm_zone; + j->tm_gmtoff = lt.tm_gmtoff; + j->tm_zone = lt.tm_zone; #endif - j->tm_isdst = lt.tm_isdst; + j->tm_isdst = lt.tm_isdst; } /* * Calculates UTC epoch difference of a desired date by measure of days. */ -int jalali_get_diff(const struct jtm* j) -{ - int p = 0; - int i; - int s, sd; - int e, ed; - int f = 1; - - if (j->tm_yday > 365 || j->tm_yday < 0) - return -1; - - if (j->tm_year == J_UTC_EPOCH_YEAR) { - p = j->tm_yday - J_UTC_EPOCH_DIFF; - return p; - } - else if (j->tm_year > J_UTC_EPOCH_YEAR) { - s = J_UTC_EPOCH_YEAR + 1; - sd = J_UTC_EPOCH_DIFF; - e = j->tm_year - 1; - ed = j->tm_yday + 1; - } else { - f = -1; - s = j->tm_year + 1; - sd = j->tm_yday; - e = J_UTC_EPOCH_YEAR - 1; - ed = J_UTC_EPOCH_DIFF + 1; - } - - for (i=s; i<=e; i++) { - p+= jalali_is_jleap(i) ? JALALI_LEAP_YEAR_LENGTH_IN_DAYS : - JALALI_NORMAL_YEAR_LENGTH_IN_DAYS; - } - - int r = jalali_is_jleap(s) ? JALALI_LEAP_YEAR_LENGTH_IN_DAYS - sd - 1 : - JALALI_NORMAL_YEAR_LENGTH_IN_DAYS - sd - 1; - - p += r + ed; - p*= f; - +int jalali_get_diff(const struct jtm *j) { + int p = 0; + int i; + int s, sd; + int e, ed; + int f = 1; + + if (j->tm_yday > 365 || j->tm_yday < 0) + return -1; + + if (j->tm_year == J_UTC_EPOCH_YEAR) { + p = j->tm_yday - J_UTC_EPOCH_DIFF; return p; + } else if (j->tm_year > J_UTC_EPOCH_YEAR) { + s = J_UTC_EPOCH_YEAR + 1; + sd = J_UTC_EPOCH_DIFF; + e = j->tm_year - 1; + ed = j->tm_yday + 1; + } else { + f = -1; + s = j->tm_year + 1; + sd = j->tm_yday; + e = J_UTC_EPOCH_YEAR - 1; + ed = J_UTC_EPOCH_DIFF + 1; + } + + for (i = s; i <= e; i++) { + p += jalali_is_jleap(i) ? JALALI_LEAP_YEAR_LENGTH_IN_DAYS + : JALALI_NORMAL_YEAR_LENGTH_IN_DAYS; + } + + int r = jalali_is_jleap(s) ? JALALI_LEAP_YEAR_LENGTH_IN_DAYS - sd - 1 + : JALALI_NORMAL_YEAR_LENGTH_IN_DAYS - sd - 1; + + p += r + ed; + p *= f; + + return p; } /* * Number of days in provided year and month */ int jalali_year_month_days(int year, int month) { - int dim = jalali_month_len[month]; - if (month == 11 && jalali_is_jleap(year)) - dim += 1; - return dim; + int dim = jalali_month_len[month]; + if (month == 11 && jalali_is_jleap(year)) + dim += 1; + return dim; } /* * Updates a jalali date struct fields based on tm_year, tm_mon and tm_mday */ -void jalali_update(struct jtm* jtm) -{ - int dim; // number of days in current month - RECLUSTER(jtm->tm_min, jtm->tm_sec, J_MINUTE_LENGTH_IN_SECONDS); - RECLUSTER(jtm->tm_hour, jtm->tm_min, J_HOUR_LENGTH_IN_MINUTES); - RECLUSTER(jtm->tm_mday, jtm->tm_hour, J_DAY_LENGTH_IN_HOURS); - - /* start by calculating a year based on month and change month and year till mday fit */ - RECLUSTER(jtm->tm_year, jtm->tm_mon, J_YEAR_LENGTH_IN_MONTHS); - - if (jtm->tm_mday < 1) { - /* breaking months to days */ - while (jtm->tm_mday < 1) { - if (jtm->tm_mon == 0) { - jtm->tm_mon = 11; - jtm->tm_year -= 1; - } else { - jtm->tm_mon -= 1; - } - jtm->tm_mday += jalali_year_month_days(jtm->tm_year, jtm->tm_mon); - } - } else { - /* clustering days as months */ - while (jtm->tm_mday > (dim=jalali_year_month_days(jtm->tm_year, jtm->tm_mon))) { - jtm->tm_mday -= dim; - if (jtm->tm_mon == 11) { - jtm->tm_mon = 0; - jtm->tm_year += 1; - } else { - jtm->tm_mon += 1; - } - } +void jalali_update(struct jtm *jtm) { + int dim; // number of days in current month + RECLUSTER(jtm->tm_min, jtm->tm_sec, J_MINUTE_LENGTH_IN_SECONDS); + RECLUSTER(jtm->tm_hour, jtm->tm_min, J_HOUR_LENGTH_IN_MINUTES); + RECLUSTER(jtm->tm_mday, jtm->tm_hour, J_DAY_LENGTH_IN_HOURS); + + /* start by calculating a year based on month and change month and year till + * mday fit */ + RECLUSTER(jtm->tm_year, jtm->tm_mon, J_YEAR_LENGTH_IN_MONTHS); + + if (jtm->tm_mday < 1) { + /* breaking months to days */ + while (jtm->tm_mday < 1) { + if (jtm->tm_mon == 0) { + jtm->tm_mon = 11; + jtm->tm_year -= 1; + } else { + jtm->tm_mon -= 1; + } + jtm->tm_mday += jalali_year_month_days(jtm->tm_year, jtm->tm_mon); + } + } else { + /* clustering days as months */ + while (jtm->tm_mday > + (dim = jalali_year_month_days(jtm->tm_year, jtm->tm_mon))) { + jtm->tm_mday -= dim; + if (jtm->tm_mon == 11) { + jtm->tm_mon = 0; + jtm->tm_year += 1; + } else { + jtm->tm_mon += 1; + } } + } - /* date is normalized, compute tm_wday and tm_yday */ - jalali_create_days_from_date(jtm); - jalali_get_date(jalali_get_diff(jtm), jtm); + /* date is normalized, compute tm_wday and tm_yday */ + jalali_create_days_from_date(jtm); + jalali_get_date(jalali_get_diff(jtm), jtm); } /* * Displays a jalali date struct fields. * should be used for debugging purposes only. */ -void jalali_show_time(const struct jtm* j) -{ - printf("%d/%02d/%02d (%02d:%02d:%02d) [%d]", - j->tm_year, j->tm_mon + 1, j->tm_mday, j->tm_hour, j->tm_min, - j->tm_sec, j->tm_wday); - printf(" yday: %d, dst: %d, off: %ld, zone: %s\n", - j->tm_yday, j->tm_isdst, j->tm_gmtoff, - j->tm_zone); +void jalali_show_time(const struct jtm *j) { + printf("%d/%02d/%02d (%02d:%02d:%02d) [%d]", j->tm_year, j->tm_mon + 1, + j->tm_mday, j->tm_hour, j->tm_min, j->tm_sec, j->tm_wday); + printf(" yday: %d, dst: %d, off: %ld, zone: %s\n", j->tm_yday, j->tm_isdst, + j->tm_gmtoff, j->tm_zone); } diff --git a/sources/libjalali/jalali.h b/sources/libjalali/jalali.h index c69463d..fa17707 100644 --- a/sources/libjalali/jalali.h +++ b/sources/libjalali/jalali.h @@ -34,57 +34,56 @@ extern "C" { #define LIBJALALI_VERSION "0.4.1gitd9200f" struct jtm { - int tm_sec; /* Seconds. (0-59) */ - int tm_min; /* Minutes. (0-59) */ - int tm_hour; /* Hours. (0-59) */ - int tm_mday; /* Day of the month. (1-31) */ - int tm_mon; /* Month. (0-11) */ - int tm_year; /* Year. */ - int tm_wday; /* Day of the week. (0-6) */ - int tm_yday; /* Day in the year. (0-365) */ - int tm_isdst; /* Daylight saving time is in effect. */ - long int tm_gmtoff; /* Seconds east of UTC. */ - const char *tm_zone; /* Timezone abbreviation. */ + int tm_sec; /* Seconds. (0-59) */ + int tm_min; /* Minutes. (0-59) */ + int tm_hour; /* Hours. (0-59) */ + int tm_mday; /* Day of the month. (1-31) */ + int tm_mon; /* Month. (0-11) */ + int tm_year; /* Year. */ + int tm_wday; /* Day of the week. (0-6) */ + int tm_yday; /* Day in the year. (0-365) */ + int tm_isdst; /* Daylight saving time is in effect. */ + long int tm_gmtoff; /* Seconds east of UTC. */ + const char *tm_zone; /* Timezone abbreviation. */ }; struct ab_jtm { - int ab_sec; - int ab_min; - int ab_hour; - int ab_days; + int ab_sec; + int ab_min; + int ab_hour; + int ab_days; }; struct jyinfo { - int lf; /* leap indicator flag */ - int y; /* year */ - int r; /* reamining years in grand cycle */ - int p; /* passed years from grand cycle*/ - int rl; /* remaining leap years in grand cycle */ - int pl; /* passed leap years in grand cycle */ - int apl; /* absolute passed leaps */ + int lf; /* leap indicator flag */ + int y; /* year */ + int r; /* reamining years in grand cycle */ + int p; /* passed years from grand cycle*/ + int rl; /* remaining leap years in grand cycle */ + int pl; /* passed leap years in grand cycle */ + int apl; /* absolute passed leaps */ }; - /* Jalali leap year indication function. */ extern int jalali_is_jleap(int year); -extern void jalali_create_time_from_secs(time_t time, struct ab_jtm* ab_jtm); +extern void jalali_create_time_from_secs(time_t time, struct ab_jtm *ab_jtm); -extern time_t jalali_create_secs_from_time(const struct ab_jtm* ab_jtm); +extern time_t jalali_create_secs_from_time(const struct ab_jtm *ab_jtm); -extern int jalali_create_date_from_days(struct jtm* j); +extern int jalali_create_date_from_days(struct jtm *j); -extern int jalali_create_days_from_date(struct jtm* j); +extern int jalali_create_days_from_date(struct jtm *j); -extern void jalali_get_jyear_info(struct jyinfo* jyinfo); +extern void jalali_get_jyear_info(struct jyinfo *jyinfo); -extern void jalali_get_date(int p, struct jtm* jtm); +extern void jalali_get_date(int p, struct jtm *jtm); -extern int jalali_get_diff(const struct jtm* jtm); +extern int jalali_get_diff(const struct jtm *jtm); -extern void jalali_update(struct jtm* jtm); +extern void jalali_update(struct jtm *jtm); -extern void jalali_show_time(const struct jtm* j); +extern void jalali_show_time(const struct jtm *j); extern int jalali_year_month_days(int year, int month); diff --git a/sources/libjalali/jconfig.h b/sources/libjalali/jconfig.h index 11a7207..437fc8e 100644 --- a/sources/libjalali/jconfig.h +++ b/sources/libjalali/jconfig.h @@ -22,16 +22,16 @@ #ifndef JCONFIG_H #define JCONFIG_H -#define JALALI_LEAP_BASE 475 /* Jalali 2820 year period epoch. */ +#define JALALI_LEAP_BASE 475 /* Jalali 2820 year period epoch. */ #define JALALI_LEAP_PERIOD 2820 /* Jalali recurring pattern length. */ #define JALALI_NORMAL_CYCLE_LENGTH 128 /* A normal cycle length. */ -#define JALALI_EXTRA_CYCLE_LENGTH 132 /* Last cycle length. */ +#define JALALI_EXTRA_CYCLE_LENGTH 132 /* Last cycle length. */ /* Starting year of the last cycle in the period. */ #define JALALI_LAST_CYCLE_START 2688 -#define J_PT0 0 /* No partitions passed. */ +#define J_PT0 0 /* No partitions passed. */ #define J_PT1 29 /* First partition passed. 0+29 */ #define J_PT2 62 /* Second partition passed. 0+29+33 */ #define J_PT3 95 /* Third partition passed. 0+29+33+33 */ @@ -41,8 +41,8 @@ #define J_L2 15 #define J_L3 23 -#define J_C1 29 /* First type of partitions, 29 years in length. */ -#define J_C2 33 /* Second type of partitions, 33 years in length. */ +#define J_C1 29 /* First type of partitions, 29 years in length. */ +#define J_C2 33 /* Second type of partitions, 33 years in length. */ #define J_C2e 37 /* Extension to the second type, only one instance. */ #define J_LI 4 /* Multiples of four are leap except for zero. */ diff --git a/sources/libjalali/jtime.c b/sources/libjalali/jtime.c index 319dbdd..e30e04d 100644 --- a/sources/libjalali/jtime.c +++ b/sources/libjalali/jtime.c @@ -20,862 +20,831 @@ */ #include -#include #include +#include #include -#include "jconfig.h" + #include "jalali.h" +#include "jconfig.h" #include "jtime.h" -const char* GMT_ZONE = "UTC"; -const char* GMT_ZONE_fa = "گرینویچ"; -const char* jalali_months[] = { "Farvardin", "Ordibehesht", "Khordaad", - "Tir", "Mordaad", "Shahrivar", "Mehr", - "Aabaan", "Aazar", "Dey", "Bahman", "Esfand" }; -const char* fa_jalali_months[] = { "فروردین", "اردیبهشت", "خرداد", - "تیر", "مرداد", "شهریور", - "مهر", "آبان", "آذر", - "دی", "بهمن", "اسفند" }; -const char* jalali_months_3[] = { "Far", "Ord", "Kho", "Tir", "Mor", "Sha", - "Meh", "Aba", "Aza", "Dey", "Bah", "Esf" }; -const char* fa_jalali_months_3[] = { "فرو", "ارد", "خرد", "تیر", "مرد", "شهر", - "مهر", "آبا", "آذر", "دی ", "بهم", "اسف"}; -const char* jalali_days_fa[] = { "Shanbeh", "Yek-Shanbeh", "Do-Shanbeh", - "Seh-Shanbeh", "Chahaar-Shanbeh", - "Panj-Shanbeh", "Jomeh" }; -const char* fa_jalali_days[] = { "شنبه", "یکشنبه", "دوشنبه", "سه شنبه", - "چهارشنبه", "پنجشنبه", "جمعه" }; -const char* jalali_days_3_fa[] = { "Sha", "Yek", "Dos", "Ses", "Cha", "Pan", - "Jom" }; -const char* fa_jalali_days_3[] = { "شنب", "یکش", "دوش", "سهش", "چها", "پنج", - "جمع" }; -const char* jalali_days_2_fa[] = { "Sh", "Ye", "Do", "Se", "Ch", "Pa", "Jo" }; - -const char* fa_jalali_days_2[] = { "شن", "یک", "دو", "سه", "چه", "پن", "جم" }; -const char* jalali_days[] = { "Saturday", "Sunday", "Monday", "Tuesday", - "Wednesday", "Thursday", "Friday" }; -const char* jalali_days_3[] = { "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", - "Fri" }; -const char* jalali_days_2[] = { "Sa", "Su", "Mo", "Tu", "We", "Th", "Fr" }; -const char* farsi_digits[] = { "۰", "۱", "۲", "۳", "۴", - "۵", "۶", "۷", "۸", "۹" }; - -const char* tzname_fa[2] = { "زمان زمستانی", "زمان تابستانی" }; +const char *GMT_ZONE = "UTC"; +const char *GMT_ZONE_fa = "گرینویچ"; +const char *jalali_months[] = { + "Farvardin", "Ordibehesht", "Khordaad", "Tir", "Mordaad", "Shahrivar", + "Mehr", "Aabaan", "Aazar", "Dey", "Bahman", "Esfand"}; +const char *fa_jalali_months[] = {"فروردین", "اردیبهشت", "خرداد", "تیر", + "مرداد", "شهریور", "مهر", "آبان", + "آذر", "دی", "بهمن", "اسفند"}; +const char *jalali_months_3[] = {"Far", "Ord", "Kho", "Tir", "Mor", "Sha", + "Meh", "Aba", "Aza", "Dey", "Bah", "Esf"}; +const char *fa_jalali_months_3[] = {"فرو", "ارد", "خرد", "تیر", "مرد", "شهر", + "مهر", "آبا", "آذر", "دی ", "بهم", "اسف"}; +const char *jalali_days_fa[] = { + "Shanbeh", "Yek-Shanbeh", "Do-Shanbeh", "Seh-Shanbeh", + "Chahaar-Shanbeh", "Panj-Shanbeh", "Jomeh"}; +const char *fa_jalali_days[] = {"شنبه", "یکشنبه", "دوشنبه", "سه شنبه", + "چهارشنبه", "پنجشنبه", "جمعه"}; +const char *jalali_days_3_fa[] = {"Sha", "Yek", "Dos", "Ses", + "Cha", "Pan", "Jom"}; +const char *fa_jalali_days_3[] = {"شنب", "یکش", "دوش", "سهش", + "چها", "پنج", "جمع"}; +const char *jalali_days_2_fa[] = {"Sh", "Ye", "Do", "Se", "Ch", "Pa", "Jo"}; + +const char *fa_jalali_days_2[] = {"شن", "یک", "دو", "سه", "چه", "پن", "جم"}; +const char *jalali_days[] = {"Saturday", "Sunday", "Monday", "Tuesday", + "Wednesday", "Thursday", "Friday"}; +const char *jalali_days_3[] = {"Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri"}; +const char *jalali_days_2[] = {"Sa", "Su", "Mo", "Tu", "We", "Th", "Fr"}; +const char *farsi_digits[] = {"۰", "۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹"}; + +const char *tzname_fa[2] = {"زمان زمستانی", "زمان تابستانی"}; static char in_buf[MAX_BUF_SIZE] = {0}; static struct jtm in_jtm; -extern char* tzname[2]; +extern char *tzname[2]; extern const int jalali_month_len[]; -void in_jasctime(const struct jtm* jtm, char* buf) -{ - if (!jtm) - return; - - if (jtm->tm_wday < 0 || jtm->tm_wday > 6) - return; - - if (jtm->tm_mon < 0 || jtm->tm_mon > 11) - return; - - if (jtm->tm_mday < 1 || jtm->tm_mday > 31) - return; - - if (buf) { - sprintf(buf, "%s %s %02d %02d:%02d:%02d %d\n", - jalali_days_3_fa[jtm->tm_wday], jalali_months_3[jtm->tm_mon], - jtm->tm_mday, jtm->tm_hour, jtm->tm_min, jtm->tm_sec, - jtm->tm_year); - } else { - snprintf(in_buf, MAX_BUF_SIZE, "%s %s %02d %02d:%02d:%02d %d\n", - jalali_days_3_fa[jtm->tm_wday], jalali_months_3[jtm->tm_mon], - jtm->tm_mday, jtm->tm_hour, jtm->tm_min, jtm->tm_sec, - jtm->tm_year); - - } +void in_jasctime(const struct jtm *jtm, char *buf) { + if (!jtm) + return; + + if (jtm->tm_wday < 0 || jtm->tm_wday > 6) + return; + + if (jtm->tm_mon < 0 || jtm->tm_mon > 11) + return; + + if (jtm->tm_mday < 1 || jtm->tm_mday > 31) + return; + + if (buf) { + sprintf(buf, "%s %s %02d %02d:%02d:%02d %d\n", + jalali_days_3_fa[jtm->tm_wday], jalali_months_3[jtm->tm_mon], + jtm->tm_mday, jtm->tm_hour, jtm->tm_min, jtm->tm_sec, jtm->tm_year); + } else { + snprintf(in_buf, MAX_BUF_SIZE, "%s %s %02d %02d:%02d:%02d %d\n", + jalali_days_3_fa[jtm->tm_wday], jalali_months_3[jtm->tm_mon], + jtm->tm_mday, jtm->tm_hour, jtm->tm_min, jtm->tm_sec, + jtm->tm_year); + } } -void in_jlocaltime(const time_t* timep, struct jtm* result) -{ - if (!timep) - return; +void in_jlocaltime(const time_t *timep, struct jtm *result) { + if (!timep) + return; - struct tm t; - struct jtm c_jtm; - struct ab_jtm ab; - long int gmtoff; - time_t c; + struct tm t; + struct jtm c_jtm; + struct ab_jtm ab; + long int gmtoff; + time_t c; - tzset(); + tzset(); - localtime_r(timep, &t); + localtime_r(timep, &t); #if defined _WIN32 || defined __MINGW32__ || defined __CYGWIN__ - struct timeval tv; - struct timezone tz; + struct timeval tv; + struct timezone tz; - gettimeofday(&tv, &tz); - gmtoff = (-tz.tz_minuteswest) * J_MINUTE_LENGTH_IN_SECONDS + - (tz.tz_dsttime * J_HOUR_LENGTH_IN_SECONDS); - c_jtm.tm_zone = tzname[t.tm_isdst]; + gettimeofday(&tv, &tz); + gmtoff = (-tz.tz_minuteswest) * J_MINUTE_LENGTH_IN_SECONDS + + (tz.tz_dsttime * J_HOUR_LENGTH_IN_SECONDS); + c_jtm.tm_zone = tzname[t.tm_isdst]; #else - gmtoff = t.tm_gmtoff; - c_jtm.tm_zone = t.tm_zone; + gmtoff = t.tm_gmtoff; + c_jtm.tm_zone = t.tm_zone; #endif - c = (*timep) + (time_t) gmtoff; + c = (*timep) + (time_t)gmtoff; - jalali_create_time_from_secs(c, &ab); - jalali_get_date(ab.ab_days, &c_jtm); - jalali_create_date_from_days(&c_jtm); - c_jtm.tm_sec = ab.ab_sec; - c_jtm.tm_min = ab.ab_min; - c_jtm.tm_hour = ab.ab_hour; - c_jtm.tm_isdst = t.tm_isdst; + jalali_create_time_from_secs(c, &ab); + jalali_get_date(ab.ab_days, &c_jtm); + jalali_create_date_from_days(&c_jtm); + c_jtm.tm_sec = ab.ab_sec; + c_jtm.tm_min = ab.ab_min; + c_jtm.tm_hour = ab.ab_hour; + c_jtm.tm_isdst = t.tm_isdst; - c_jtm.tm_gmtoff = gmtoff; - memcpy(result ? result : &in_jtm, &c_jtm, sizeof(struct jtm)); + c_jtm.tm_gmtoff = gmtoff; + memcpy(result ? result : &in_jtm, &c_jtm, sizeof(struct jtm)); } -void in_jctime(const time_t* timep, char* buf) -{ - if (!timep) - return; +void in_jctime(const time_t *timep, char *buf) { + if (!timep) + return; - struct jtm c_jtm; - in_jlocaltime(timep, &c_jtm); + struct jtm c_jtm; + in_jlocaltime(timep, &c_jtm); - in_jasctime(&c_jtm, buf ? buf : 0); + in_jasctime(&c_jtm, buf ? buf : 0); } -void in_jgmtime(const time_t* timep, struct jtm* result) -{ - if (!timep) - return; +void in_jgmtime(const time_t *timep, struct jtm *result) { + if (!timep) + return; - struct tm t; - struct jtm c_jtm; - struct ab_jtm ab; - time_t c; - tzset(); + struct tm t; + struct jtm c_jtm; + struct ab_jtm ab; + time_t c; + tzset(); - gmtime_r(timep, &t); - c = *timep; + gmtime_r(timep, &t); + c = *timep; - jalali_create_time_from_secs(c, &ab); - jalali_get_date(ab.ab_days, &c_jtm); - jalali_create_date_from_days(&c_jtm); - c_jtm.tm_sec = ab.ab_sec; - c_jtm.tm_min = ab.ab_min; - c_jtm.tm_hour = ab.ab_hour; - c_jtm.tm_isdst = 0; + jalali_create_time_from_secs(c, &ab); + jalali_get_date(ab.ab_days, &c_jtm); + jalali_create_date_from_days(&c_jtm); + c_jtm.tm_sec = ab.ab_sec; + c_jtm.tm_min = ab.ab_min; + c_jtm.tm_hour = ab.ab_hour; + c_jtm.tm_isdst = 0; - c_jtm.tm_zone = GMT_ZONE; - c_jtm.tm_gmtoff = 0; + c_jtm.tm_zone = GMT_ZONE; + c_jtm.tm_gmtoff = 0; - memcpy(result ? result : &in_jtm, &c_jtm, sizeof(struct jtm)); + memcpy(result ? result : &in_jtm, &c_jtm, sizeof(struct jtm)); } -char* jasctime(const struct jtm* jtm) -{ - if (!jtm) - return 0; +char *jasctime(const struct jtm *jtm) { + if (!jtm) + return 0; - in_jasctime(jtm, 0); + in_jasctime(jtm, 0); - return in_buf; + return in_buf; } -char* jctime(const time_t* timep) -{ - if (!timep) - return 0; +char *jctime(const time_t *timep) { + if (!timep) + return 0; - in_jctime(timep, 0); + in_jctime(timep, 0); - return in_buf; + return in_buf; } -struct jtm* jgmtime(const time_t* timep) -{ - if (!timep) - return 0; - in_jgmtime(timep, 0); +struct jtm *jgmtime(const time_t *timep) { + if (!timep) + return 0; + in_jgmtime(timep, 0); - return &in_jtm; + return &in_jtm; } -struct jtm* jlocaltime(const time_t* timep) -{ - if (!timep) - return 0; +struct jtm *jlocaltime(const time_t *timep) { + if (!timep) + return 0; - in_jlocaltime(timep, 0); + in_jlocaltime(timep, 0); - return &in_jtm; + return &in_jtm; } -time_t jmktime(struct jtm* jtm) -{ - if (!jtm) - return (time_t) (-1); - - tzset(); - jalali_update(jtm); - int p = jalali_get_diff(jtm); - time_t t; - t = ((time_t) p * (time_t) J_DAY_LENGTH_IN_SECONDS) + - ((time_t) jtm->tm_hour * (time_t) J_HOUR_LENGTH_IN_SECONDS) - + ((time_t) jtm->tm_min * - (time_t) J_MINUTE_LENGTH_IN_SECONDS) + (time_t) jtm->tm_sec - - ((time_t) jtm->tm_gmtoff); - - return t; +time_t jmktime(struct jtm *jtm) { + if (!jtm) + return (time_t)(-1); + + tzset(); + jalali_update(jtm); + int p = jalali_get_diff(jtm); + time_t t; + t = ((time_t)p * (time_t)J_DAY_LENGTH_IN_SECONDS) + + ((time_t)jtm->tm_hour * (time_t)J_HOUR_LENGTH_IN_SECONDS) + + ((time_t)jtm->tm_min * (time_t)J_MINUTE_LENGTH_IN_SECONDS) + + (time_t)jtm->tm_sec - ((time_t)jtm->tm_gmtoff); + + return t; } -size_t jstrftime(char* s, size_t max, const char* format, const struct jtm* jtm) -{ - if (!s || max <= 0 || !format || !jtm) - return -1; - - char _l1[10]; - char _l2[10]; - char _l3[10]; - char _la[100]; - char _lb[100]; - char buf[MAX_BUF_SIZE]; - int i, j; - int fmt_n = strlen(format); - int rb = 0; - int b_n; - int tmp; - int tmp1; - time_t t; - struct jtm t_j; - - for (i=0; itm_wday], MAX_BUF_SIZE); - break; - - /* The full weekday name. */ - case 'A': - strncpy(buf, jalali_days[jtm->tm_wday], MAX_BUF_SIZE); - break; - - /* The abbreviated month name. */ - case 'b': - strncpy(buf, jalali_months_3[jtm->tm_mon], MAX_BUF_SIZE); - break; - - /* The full month name. */ - case 'B': - strncpy(buf, jalali_months[jtm->tm_mon], MAX_BUF_SIZE); - break; - - /* - * The preferred date and time representation. - * example: Tue 27 Ord 1390 03:28:19 IRDT. - */ - case 'c': - tzset(); - snprintf(buf, MAX_BUF_SIZE, "%s %d %s %d %02d:%02d:%02d %s", - jalali_days_3_fa[jtm->tm_wday], jtm->tm_mday, - jalali_months_3[jtm->tm_mon], jtm->tm_year, - jtm->tm_hour, jtm->tm_min, jtm->tm_sec, - jtm->tm_zone); - break; - - /* The century number (year/100) as a 2-digit integer. */ - case 'C': - snprintf(buf, MAX_BUF_SIZE, "%d", (jtm->tm_year / 100) + 1); - break; - - /* The day of the month as a decimal number (range 01 to 31). */ - case 'd': - snprintf(buf, MAX_BUF_SIZE, "%02d", jtm->tm_mday); - break; - - /* Equivalent to %Y/%m/%d. */ - case 'D': - snprintf(buf, MAX_BUF_SIZE, "%d/%02d/%02d", jtm->tm_year, - jtm->tm_mon + 1, jtm->tm_mday); - break; - - /* - * Like %d, the day of the month as a decimal number, but - * a leading zero is replaced by a space. - */ - case 'e': - snprintf(buf, MAX_BUF_SIZE, "%2d", jtm->tm_mday); - break; - - /* - * The preferred date and time representation in Farsi. (utf8) - * example: سه شنبه ۱۷ خرداد ۱۳۹۰، ساعت ۰۸:۱۹:۲۳ (IRDT) - */ - case 'E': - tzset(); - jalali_to_farsi(_l1, 10, 2, "۰", jtm->tm_hour); - jalali_to_farsi(_l2, 10, 2, "۰", jtm->tm_min); - jalali_to_farsi(_l3, 10, 2, "۰", jtm->tm_sec); - jalali_to_farsi(_la, 100, 2, "۰", jtm->tm_mday); - jalali_to_farsi(_lb, 100, 0, " ", jtm->tm_year); - snprintf(buf, MAX_BUF_SIZE, "%s %s %s %s، ساعت %s:%s:%s - %s", - fa_jalali_days[jtm->tm_wday], _la, - fa_jalali_months[jtm->tm_mon], _lb, - _l1, _l2, _l3, - (jtm->tm_zone == GMT_ZONE) ? GMT_ZONE_fa : - tzname_fa[jtm->tm_isdst]); - - break; - - /* - * Equivalent to %Y-%m-%d (similar to the ISO 8601 date format). - */ - case 'F': - snprintf(buf, MAX_BUF_SIZE, "%d-%02d-%02d", jtm->tm_year, - jtm->tm_mon + 1, jtm->tm_mday); - break; - - /* The abbreviated weekday name. (Farsi-UTF8) */ - case 'g': - strncpy(buf, fa_jalali_days_3[jtm->tm_wday], MAX_BUF_SIZE); - break; - - /* The full weekday name. (Farsi-UTF8) */ - case 'G': - strncpy(buf, fa_jalali_days[jtm->tm_wday], MAX_BUF_SIZE); - break; - - /* The abbreviated month name. (Farsi-UTF8) */ - case 'v': - strncpy(buf, fa_jalali_months_3[jtm->tm_mon], MAX_BUF_SIZE); - break; - - /* The full month name. (Farsi-UTF8) */ - case 'V': - strncpy(buf, fa_jalali_months[jtm->tm_mon], MAX_BUF_SIZE); - break; - - /* The abbreviated weekday name. (Farsi) */ - case 'h': - strncpy(buf, jalali_days_3_fa[jtm->tm_wday], MAX_BUF_SIZE); - break; - - /* The full weekday name. (Farsi) */ - case 'q': - strncpy(buf, jalali_days_fa[jtm->tm_wday], MAX_BUF_SIZE); - break; - - /* - * The hour as a decimal number using a 24-hour clock - * (range 00 to 23). - */ - case 'H': - snprintf(buf, MAX_BUF_SIZE, "%02d", jtm->tm_hour); - break; - - /* - * The hour as a decimal number using a 12-hour clock - * (range 01 to 12). - */ - case 'I': - snprintf(buf, MAX_BUF_SIZE, "%02d", (jtm->tm_hour == 12) ? 12 : - jtm->tm_hour % 12); - break; - - /* - * The day of the year as a decimal number - * (range 001 to 366). - */ - case 'j': - snprintf(buf, MAX_BUF_SIZE, "%03d", jtm->tm_yday + 1); - break; - - /* - * The hour (24-hour clock) as a decimal number (range 0 to 23); - * single digits are preceded by a blank. - * (See also %H.) - */ - case 'k': - snprintf(buf, MAX_BUF_SIZE, "%2d", jtm->tm_hour); - break; - - /* - * The hour (12-hour clock) as a decimal number - * (range 1 to 12); - * single digits are preceded by a blank. - * (See also %I.) - */ - case 'l': - tmp = (jtm->tm_hour == 12) ? 12 : jtm->tm_hour % 12; - snprintf(buf, MAX_BUF_SIZE, "%2d", tmp); - break; - - /* The month as a decimal number (range 01 to 12). */ - case 'm': - snprintf(buf, MAX_BUF_SIZE, "%02d", jtm->tm_mon + 1); - break; - - /* The minute as a decimal number (range 00 to 59). */ - case 'M': - snprintf(buf, MAX_BUF_SIZE, "%02d", jtm->tm_min); - break; - - /* A newline character. */ - case 'n': - snprintf(buf, MAX_BUF_SIZE, "\n"); - break; - - /* - * Either "ق.ظ" or "ب.ظ" according to the given time value. - * Noon is treated as "ق.ظ" and midnight as "ب.ظ". - */ - case 'O': - snprintf(buf, MAX_BUF_SIZE, "%s", - (jtm->tm_hour >= 0 && jtm->tm_hour < 12) ? - "ق.ظ" : "ب.ظ"); - break; - - /* - * Either "AM" or "PM" according to the given time value. - * Noon is treated as "PM" and midnight as "AM". - */ - case 'p': - snprintf(buf, MAX_BUF_SIZE, "%s", - (jtm->tm_hour >= 0 && jtm->tm_hour < 12) ? - "AM" : "PM"); - break; - - /* Like %p but in lowercase: "am" or "pm". */ - case 'P': - snprintf(buf, MAX_BUF_SIZE, "%s", - (jtm->tm_hour >= 0 && jtm->tm_hour < 12) ? - "am" : "pm"); - break; - - /* - * The time in a.m. or p.m. notation. - * In the POSIX locale this is equivalent to %I:%M:%S %p. - */ - case 'r': - snprintf(buf, MAX_BUF_SIZE, "%02d:%02d:%02d %s", - (jtm->tm_hour == 12) ? 12 : jtm->tm_hour % 12, - jtm->tm_min, jtm->tm_sec, - (jtm->tm_hour >= 0 && jtm->tm_hour < 12) ? - "AM" : "PM"); - break; - - /* - * The time in 24-hour notation (%H:%M). - * For a version including the seconds, see %T below. - */ - case 'R': - snprintf(buf, MAX_BUF_SIZE, "%02d:%02d", jtm->tm_hour, - jtm->tm_min); - break; - - /* - * The number of seconds since the Epoch - * 1970-01-01 00:00:00 +0000 (UTC). - */ - case 's': - memcpy(&t_j, jtm, sizeof(struct jtm)); - t = jmktime(&t_j); - snprintf(buf, MAX_BUF_SIZE, "%d", (int) t); - break; - - /* The second as a decimal number (range 00 to 59). */ - case 'S': - snprintf(buf, MAX_BUF_SIZE, "%02d", jtm->tm_sec); - break; - - /* A tab character. */ - case 't': - snprintf(buf, MAX_BUF_SIZE, "\t"); - break; - - /* The time in 24-hour notation (%H:%M:%S). */ - case 'T': - snprintf(buf, MAX_BUF_SIZE, "%02d:%02d:%02d", - jtm->tm_hour, jtm->tm_min, jtm->tm_sec); - break; - - /* - * The day of the week as a decimal, range 1 to 7 - * Saturday being 1. See also %w. - */ - case 'u': - snprintf(buf, MAX_BUF_SIZE, "%d", jtm->tm_wday + 1); - break; - - /* - * The week number of the current year as a decimal number, - * range 00 to 53, - * starting with the first Saturday as the first day of week 01. - */ - case 'U': - memcpy(&t_j, jtm, sizeof(struct jtm)); - t_j.tm_yday = 0; - jalali_create_date_from_days(&t_j); - tmp = (jtm->tm_yday + t_j.tm_wday) / 7; - snprintf(buf, MAX_BUF_SIZE, "%02d", tmp); - break; - - /* - * The day of the week as a decimal, range 0 to 6 - * Saturday being 0. See also %u. - */ - case 'w': - snprintf(buf, MAX_BUF_SIZE, "%d", jtm->tm_wday); - break; - - /* - * The preferred date representation without the time - * in Farsi. (utf8) - */ - case 'W': - jalali_to_farsi(_la, 100, 0, " ", jtm->tm_year); - jalali_to_farsi(_l1, 10, 2, "۰", jtm->tm_mon+1); - jalali_to_farsi(_l2, 10, 2, "۰", jtm->tm_mday); - - snprintf(buf, MAX_BUF_SIZE, "%s/%s/%s", _la, - _l1, _l2); - break; - - /* The preferred date representation without the time. */ - case 'x': - snprintf(buf, MAX_BUF_SIZE, "%02d/%02d/%d", - jtm->tm_mday, jtm->tm_mon+1, jtm->tm_year); - break; - - /* - * The preferred time representation in Farsi. (utf8) - */ - case 'X': - jalali_to_farsi(_l1, 10, 2, "۰", jtm->tm_hour); - jalali_to_farsi(_l2, 10, 2, "۰", jtm->tm_min); - jalali_to_farsi(_l3, 10, 2, "۰", jtm->tm_sec); - - snprintf(buf, MAX_BUF_SIZE, "%s:%s:%s", - _l1, _l2, _l3); - - break; - - /* - * The year as a decimal number without a century - * (range 00 to 99). - */ - case 'y': - tmp = ((jtm->tm_year) % 1000) % 100; - snprintf(buf, MAX_BUF_SIZE, "%02d", tmp); - break; - - /* The year as a decimal number including the century. */ - case 'Y': - snprintf(buf, MAX_BUF_SIZE, "%d", jtm->tm_year); - break; - - /* - * The +hhmm or -hhmm numeric timezone - * (that is, the hour and minute offset from UTC). - */ - case 'z': - tmp = ((int)jtm->tm_gmtoff / J_HOUR_LENGTH_IN_SECONDS); - tmp1 = ((int)jtm->tm_gmtoff % J_HOUR_LENGTH_IN_SECONDS) / - J_MINUTE_LENGTH_IN_SECONDS; - snprintf(buf, MAX_BUF_SIZE, "%s%02d%02d", - (tmp >= 0) ? "+" : "-", abs(tmp), abs(tmp1)); - break; - - /* The timezone or name or abbreviation. */ - case 'Z': - snprintf(buf, MAX_BUF_SIZE, "%s", jtm->tm_zone); - break; - - /* A literal '%' character. */ - case '%': - snprintf(buf, MAX_BUF_SIZE, "%s", "%"); - break; - - /* Non of the above. Ignoring modifier. */ - default: - break; - } - - b_n = strlen(buf); - for (j=0; j (int) (max - 2)) { - s[max-1] = '\0'; - return (max-1); - } - - s[rb] = buf[j]; - rb++; - } - i++; - _la[0] = 0; - _lb[0] = 0; - _l1[0] = 0; - _l2[0] = 0; - _l3[0] = 0; +size_t jstrftime(char *s, size_t max, const char *format, + const struct jtm *jtm) { + if (!s || max <= 0 || !format || !jtm) + return -1; + + char _l1[10]; + char _l2[10]; + char _l3[10]; + char _la[100]; + char _lb[100]; + char buf[MAX_BUF_SIZE]; + int i, j; + int fmt_n = strlen(format); + int rb = 0; + int b_n; + int tmp; + int tmp1; + time_t t; + struct jtm t_j; + + for (i = 0; i < fmt_n && rb < (int)(max - 1); i++) { + if (format[i] != '%') { + s[rb] = format[i]; + rb++; + } else { + buf[0] = '\0'; + switch (format[i + 1]) { + /* The abbreviated weekday name. */ + case 'a': + strncpy(buf, jalali_days_3[jtm->tm_wday], MAX_BUF_SIZE); + break; + + /* The full weekday name. */ + case 'A': + strncpy(buf, jalali_days[jtm->tm_wday], MAX_BUF_SIZE); + break; + + /* The abbreviated month name. */ + case 'b': + strncpy(buf, jalali_months_3[jtm->tm_mon], MAX_BUF_SIZE); + break; + + /* The full month name. */ + case 'B': + strncpy(buf, jalali_months[jtm->tm_mon], MAX_BUF_SIZE); + break; + + /* + * The preferred date and time representation. + * example: Tue 27 Ord 1390 03:28:19 IRDT. + */ + case 'c': + tzset(); + snprintf(buf, MAX_BUF_SIZE, "%s %d %s %d %02d:%02d:%02d %s", + jalali_days_3_fa[jtm->tm_wday], jtm->tm_mday, + jalali_months_3[jtm->tm_mon], jtm->tm_year, jtm->tm_hour, + jtm->tm_min, jtm->tm_sec, jtm->tm_zone); + break; + + /* The century number (year/100) as a 2-digit integer. */ + case 'C': + snprintf(buf, MAX_BUF_SIZE, "%d", (jtm->tm_year / 100) + 1); + break; + + /* The day of the month as a decimal number (range 01 to 31). */ + case 'd': + snprintf(buf, MAX_BUF_SIZE, "%02d", jtm->tm_mday); + break; + + /* Equivalent to %Y/%m/%d. */ + case 'D': + snprintf(buf, MAX_BUF_SIZE, "%d/%02d/%02d", jtm->tm_year, + jtm->tm_mon + 1, jtm->tm_mday); + break; + + /* + * Like %d, the day of the month as a decimal number, but + * a leading zero is replaced by a space. + */ + case 'e': + snprintf(buf, MAX_BUF_SIZE, "%2d", jtm->tm_mday); + break; + + /* + * The preferred date and time representation in Farsi. (utf8) + * example: سه شنبه ۱۷ خرداد ۱۳۹۰، ساعت ۰۸:۱۹:۲۳ (IRDT) + */ + case 'E': + tzset(); + jalali_to_farsi(_l1, 10, 2, "۰", jtm->tm_hour); + jalali_to_farsi(_l2, 10, 2, "۰", jtm->tm_min); + jalali_to_farsi(_l3, 10, 2, "۰", jtm->tm_sec); + jalali_to_farsi(_la, 100, 2, "۰", jtm->tm_mday); + jalali_to_farsi(_lb, 100, 0, " ", jtm->tm_year); + snprintf(buf, MAX_BUF_SIZE, "%s %s %s %s، ساعت %s:%s:%s - %s", + fa_jalali_days[jtm->tm_wday], _la, + fa_jalali_months[jtm->tm_mon], _lb, _l1, _l2, _l3, + (jtm->tm_zone == GMT_ZONE) ? GMT_ZONE_fa + : tzname_fa[jtm->tm_isdst]); + + break; + + /* + * Equivalent to %Y-%m-%d (similar to the ISO 8601 date format). + */ + case 'F': + snprintf(buf, MAX_BUF_SIZE, "%d-%02d-%02d", jtm->tm_year, + jtm->tm_mon + 1, jtm->tm_mday); + break; + + /* The abbreviated weekday name. (Farsi-UTF8) */ + case 'g': + strncpy(buf, fa_jalali_days_3[jtm->tm_wday], MAX_BUF_SIZE); + break; + + /* The full weekday name. (Farsi-UTF8) */ + case 'G': + strncpy(buf, fa_jalali_days[jtm->tm_wday], MAX_BUF_SIZE); + break; + + /* The abbreviated month name. (Farsi-UTF8) */ + case 'v': + strncpy(buf, fa_jalali_months_3[jtm->tm_mon], MAX_BUF_SIZE); + break; + + /* The full month name. (Farsi-UTF8) */ + case 'V': + strncpy(buf, fa_jalali_months[jtm->tm_mon], MAX_BUF_SIZE); + break; + + /* The abbreviated weekday name. (Farsi) */ + case 'h': + strncpy(buf, jalali_days_3_fa[jtm->tm_wday], MAX_BUF_SIZE); + break; + + /* The full weekday name. (Farsi) */ + case 'q': + strncpy(buf, jalali_days_fa[jtm->tm_wday], MAX_BUF_SIZE); + break; + + /* + * The hour as a decimal number using a 24-hour clock + * (range 00 to 23). + */ + case 'H': + snprintf(buf, MAX_BUF_SIZE, "%02d", jtm->tm_hour); + break; + + /* + * The hour as a decimal number using a 12-hour clock + * (range 01 to 12). + */ + case 'I': + snprintf(buf, MAX_BUF_SIZE, "%02d", + (jtm->tm_hour == 12) ? 12 : jtm->tm_hour % 12); + break; + + /* + * The day of the year as a decimal number + * (range 001 to 366). + */ + case 'j': + snprintf(buf, MAX_BUF_SIZE, "%03d", jtm->tm_yday + 1); + break; + + /* + * The hour (24-hour clock) as a decimal number (range 0 to 23); + * single digits are preceded by a blank. + * (See also %H.) + */ + case 'k': + snprintf(buf, MAX_BUF_SIZE, "%2d", jtm->tm_hour); + break; + + /* + * The hour (12-hour clock) as a decimal number + * (range 1 to 12); + * single digits are preceded by a blank. + * (See also %I.) + */ + case 'l': + tmp = (jtm->tm_hour == 12) ? 12 : jtm->tm_hour % 12; + snprintf(buf, MAX_BUF_SIZE, "%2d", tmp); + break; + + /* The month as a decimal number (range 01 to 12). */ + case 'm': + snprintf(buf, MAX_BUF_SIZE, "%02d", jtm->tm_mon + 1); + break; + + /* The minute as a decimal number (range 00 to 59). */ + case 'M': + snprintf(buf, MAX_BUF_SIZE, "%02d", jtm->tm_min); + break; + + /* A newline character. */ + case 'n': + snprintf(buf, MAX_BUF_SIZE, "\n"); + break; + + /* + * Either "ق.ظ" or "ب.ظ" according to the given time value. + * Noon is treated as "ق.ظ" and midnight as "ب.ظ". + */ + case 'O': + snprintf(buf, MAX_BUF_SIZE, "%s", + (jtm->tm_hour >= 0 && jtm->tm_hour < 12) ? "ق.ظ" : "ب.ظ"); + break; + + /* + * Either "AM" or "PM" according to the given time value. + * Noon is treated as "PM" and midnight as "AM". + */ + case 'p': + snprintf(buf, MAX_BUF_SIZE, "%s", + (jtm->tm_hour >= 0 && jtm->tm_hour < 12) ? "AM" : "PM"); + break; + + /* Like %p but in lowercase: "am" or "pm". */ + case 'P': + snprintf(buf, MAX_BUF_SIZE, "%s", + (jtm->tm_hour >= 0 && jtm->tm_hour < 12) ? "am" : "pm"); + break; + + /* + * The time in a.m. or p.m. notation. + * In the POSIX locale this is equivalent to %I:%M:%S %p. + */ + case 'r': + snprintf(buf, MAX_BUF_SIZE, "%02d:%02d:%02d %s", + (jtm->tm_hour == 12) ? 12 : jtm->tm_hour % 12, jtm->tm_min, + jtm->tm_sec, + (jtm->tm_hour >= 0 && jtm->tm_hour < 12) ? "AM" : "PM"); + break; + + /* + * The time in 24-hour notation (%H:%M). + * For a version including the seconds, see %T below. + */ + case 'R': + snprintf(buf, MAX_BUF_SIZE, "%02d:%02d", jtm->tm_hour, jtm->tm_min); + break; + + /* + * The number of seconds since the Epoch + * 1970-01-01 00:00:00 +0000 (UTC). + */ + case 's': + memcpy(&t_j, jtm, sizeof(struct jtm)); + t = jmktime(&t_j); + snprintf(buf, MAX_BUF_SIZE, "%d", (int)t); + break; + + /* The second as a decimal number (range 00 to 59). */ + case 'S': + snprintf(buf, MAX_BUF_SIZE, "%02d", jtm->tm_sec); + break; + + /* A tab character. */ + case 't': + snprintf(buf, MAX_BUF_SIZE, "\t"); + break; + + /* The time in 24-hour notation (%H:%M:%S). */ + case 'T': + snprintf(buf, MAX_BUF_SIZE, "%02d:%02d:%02d", jtm->tm_hour, jtm->tm_min, + jtm->tm_sec); + break; + + /* + * The day of the week as a decimal, range 1 to 7 + * Saturday being 1. See also %w. + */ + case 'u': + snprintf(buf, MAX_BUF_SIZE, "%d", jtm->tm_wday + 1); + break; + + /* + * The week number of the current year as a decimal number, + * range 00 to 53, + * starting with the first Saturday as the first day of week 01. + */ + case 'U': + memcpy(&t_j, jtm, sizeof(struct jtm)); + t_j.tm_yday = 0; + jalali_create_date_from_days(&t_j); + tmp = (jtm->tm_yday + t_j.tm_wday) / 7; + snprintf(buf, MAX_BUF_SIZE, "%02d", tmp); + break; + + /* + * The day of the week as a decimal, range 0 to 6 + * Saturday being 0. See also %u. + */ + case 'w': + snprintf(buf, MAX_BUF_SIZE, "%d", jtm->tm_wday); + break; + + /* + * The preferred date representation without the time + * in Farsi. (utf8) + */ + case 'W': + jalali_to_farsi(_la, 100, 0, " ", jtm->tm_year); + jalali_to_farsi(_l1, 10, 2, "۰", jtm->tm_mon + 1); + jalali_to_farsi(_l2, 10, 2, "۰", jtm->tm_mday); + + snprintf(buf, MAX_BUF_SIZE, "%s/%s/%s", _la, _l1, _l2); + break; + + /* The preferred date representation without the time. */ + case 'x': + snprintf(buf, MAX_BUF_SIZE, "%02d/%02d/%d", jtm->tm_mday, + jtm->tm_mon + 1, jtm->tm_year); + break; + + /* + * The preferred time representation in Farsi. (utf8) + */ + case 'X': + jalali_to_farsi(_l1, 10, 2, "۰", jtm->tm_hour); + jalali_to_farsi(_l2, 10, 2, "۰", jtm->tm_min); + jalali_to_farsi(_l3, 10, 2, "۰", jtm->tm_sec); + + snprintf(buf, MAX_BUF_SIZE, "%s:%s:%s", _l1, _l2, _l3); + + break; + + /* + * The year as a decimal number without a century + * (range 00 to 99). + */ + case 'y': + tmp = ((jtm->tm_year) % 1000) % 100; + snprintf(buf, MAX_BUF_SIZE, "%02d", tmp); + break; + + /* The year as a decimal number including the century. */ + case 'Y': + snprintf(buf, MAX_BUF_SIZE, "%d", jtm->tm_year); + break; + + /* + * The +hhmm or -hhmm numeric timezone + * (that is, the hour and minute offset from UTC). + */ + case 'z': + tmp = ((int)jtm->tm_gmtoff / J_HOUR_LENGTH_IN_SECONDS); + tmp1 = ((int)jtm->tm_gmtoff % J_HOUR_LENGTH_IN_SECONDS) / + J_MINUTE_LENGTH_IN_SECONDS; + snprintf(buf, MAX_BUF_SIZE, "%s%02d%02d", (tmp >= 0) ? "+" : "-", + abs(tmp), abs(tmp1)); + break; + + /* The timezone or name or abbreviation. */ + case 'Z': + snprintf(buf, MAX_BUF_SIZE, "%s", jtm->tm_zone); + break; + + /* A literal '%' character. */ + case '%': + snprintf(buf, MAX_BUF_SIZE, "%s", "%"); + break; + + /* Non of the above. Ignoring modifier. */ + default: + break; + } + + b_n = strlen(buf); + for (j = 0; j < b_n; j++) { + if (rb > (int)(max - 2)) { + s[max - 1] = '\0'; + return (max - 1); } + + s[rb] = buf[j]; + rb++; + } + i++; + _la[0] = 0; + _lb[0] = 0; + _l1[0] = 0; + _l2[0] = 0; + _l3[0] = 0; } - s[rb] = '\0'; + } + s[rb] = '\0'; - return rb; + return rb; } -char* jstrptime(const char* s, const char* format, struct jtm* jtm) -{ - char buf[MAX_BUF_SIZE]; - char delim[MAX_BUF_SIZE]; - - char* pos_n; - char* pos_c; - char* pos_e; - - char** ptr; - - size_t diff = 0, diff1 = 0; - int s_s, fmt_s, tmp; - int i, j, k, f, c = 0; - char fd; - - struct jtm _j; - time_t t; - - s_s = strlen(s); - fmt_s = strlen(format); - - /* - * Traversing format string for the matching characters in input string. - * Each time an identical character is found, we simply pass to the - * next one. In the event of finding a % (format specifier) we find the - * matching argument by means of finding the delimiter between the found - * format specifier and the next. If there was no format specifiers after - * the current one, we consider the remaining set of characters as - * delimiter. - */ - - for (i=0, j=0; i < s_s && j < fmt_s; ) { - buf[0] = 0; - delim[0] = 0; - - /* Identical character in format and string, skipping. */ - if (s[i] == format[j]) { - i++; - j++; - continue; - } +char *jstrptime(const char *s, const char *format, struct jtm *jtm) { + char buf[MAX_BUF_SIZE]; + char delim[MAX_BUF_SIZE]; - /* Malformed string or format. */ - if (format[j] != '%') { - return NULL; - } + char *pos_n; + char *pos_c; + char *pos_e; + + char **ptr; + + size_t diff = 0, diff1 = 0; + int s_s, fmt_s, tmp; + int i, j, k, f, c = 0; + char fd; + + struct jtm _j; + time_t t; + + s_s = strlen(s); + fmt_s = strlen(format); - if (j+2 >= fmt_s) { - diff1 = s_s; - } else { - pos_c = (char*) &format[j+2]; - pos_n = strchr(pos_c, '%'); - if (!pos_n) { - diff = 1; - pos_n = (char*) &format[fmt_s-1]; - } else { - diff = (pos_n - pos_c); - } - - memcpy(delim, pos_c, diff); - delim[diff] = 0; - pos_e = strstr(&s[i], delim); - - /* Delimiter not found in string. */ - if (!pos_e) { - return NULL; - } - - diff1 = (pos_e - &s[i]); + /* + * Traversing format string for the matching characters in input string. + * Each time an identical character is found, we simply pass to the + * next one. In the event of finding a % (format specifier) we find the + * matching argument by means of finding the delimiter between the found + * format specifier and the next. If there was no format specifiers after + * the current one, we consider the remaining set of characters as + * delimiter. + */ + + for (i = 0, j = 0; i < s_s && j < fmt_s;) { + buf[0] = 0; + delim[0] = 0; + + /* Identical character in format and string, skipping. */ + if (s[i] == format[j]) { + i++; + j++; + continue; + } + + /* Malformed string or format. */ + if (format[j] != '%') { + return NULL; + } + + if (j + 2 >= fmt_s) { + diff1 = s_s; + } else { + pos_c = (char *)&format[j + 2]; + pos_n = strchr(pos_c, '%'); + if (!pos_n) { + diff = 1; + pos_n = (char *)&format[fmt_s - 1]; + } else { + diff = (pos_n - pos_c); + } + + memcpy(delim, pos_c, diff); + delim[diff] = 0; + pos_e = strstr(&s[i], delim); + + /* Delimiter not found in string. */ + if (!pos_e) { + return NULL; + } + + diff1 = (pos_e - &s[i]); + } + + fd = format[j + 1]; + memcpy(buf, &s[i], diff1); + buf[diff1] = 0; + switch (fd) { + /* The abbreviated or full weekday name. */ + case 'a': + case 'A': + ptr = (fd == 'a') ? (char **)jalali_days_3 : (char **)jalali_days; + f = 0; + + for (k = 0; k < J_WEEK_LENGTH; k++) { + if (!strcasecmp(buf, ptr[k])) { + jtm->tm_wday = k; + f = 1; } + } + + if (!f) + return (char *)&s[i]; - fd = format[j+1]; - memcpy(buf, &s[i], diff1); - buf[diff1] = 0; - switch (fd) { - /* The abbreviated or full weekday name. */ - case 'a': - case 'A': - ptr = (fd == 'a') ? (char**) jalali_days_3 : (char**) jalali_days; - f = 0; - - for (k=0; ktm_wday = k; - f = 1; - } - } - - if (!f) - return (char*) &s[i]; - - break; - - /* The abbreviated or full month name. */ - case 'b': - case 'B': - ptr = (fd == 'b') ? (char**) jalali_months_3 : - (char**) jalali_months; - f = 0; - - for (k=0; ktm_mon = k; - f = 1; - } - } - - if (!f) - return (char*) &s[i]; - - break; - - /* The day of the month as a decimal number (range 01 to 31). */ - case 'd': - case 'e': - jtm->tm_mday = atoi(buf); - break; - - /* - * The hour as a decimal number using a 24-hour clock - * (range 00 to 23). - */ - case 'H': - jtm->tm_hour = atoi(buf); - break; - - /* The day of the year as a decimal number (range 001 to 366). */ - case 'j': - jtm->tm_yday = atoi(buf) - 1; - break; - - /* The month as a decimal number (range 01 to 12). */ - case 'm': - jtm->tm_mon = atoi(buf) -1; - break; - - /* The minute as a decimal number (range 00 to 59). */ - case 'M': - jtm->tm_min = atoi(buf); - break; - - /* Seconds since epoch. (1970/1/1) */ - case 's': - t = (time_t) atol(buf); - jlocaltime_r(&t, &_j); - memcpy(jtm, &_j, sizeof(struct jtm)); - break; - - /* The second as a decimal number (range 00 to 59). */ - case 'S': - jtm->tm_sec = atoi(buf); - break; - - /* - * The year as a decimal number without a century - * (range 00 to 99). - */ - case 'y': - tmp = atoi(buf); - if (tmp >= 19 && tmp < 100) - jtm->tm_year = 1300 + tmp; - else - jtm->tm_year = 1400 + tmp; - break; - - /* The year as a decimal number including the century. */ - case 'Y': - jtm->tm_year = atoi(buf); - break; - - /* The abbreviated or full weekday name. (Farsi) */ - case 'q': - case 'h': - ptr = (fd == 'h') ? (char**) jalali_days_3_fa : - (char**) jalali_days_fa; - f = 0; - - for (k=0; ktm_wday = k; - f = 1; - } - } - - if (!f) - return (char*) &s[i]; - - break; - - default: - break; + break; + + /* The abbreviated or full month name. */ + case 'b': + case 'B': + ptr = (fd == 'b') ? (char **)jalali_months_3 : (char **)jalali_months; + f = 0; + + for (k = 0; k < J_YEAR_LENGTH_IN_MONTHS; k++) { + if (!strcasecmp(buf, ptr[k])) { + jtm->tm_mon = k; + f = 1; + } + } + + if (!f) + return (char *)&s[i]; + + break; + + /* The day of the month as a decimal number (range 01 to 31). */ + case 'd': + case 'e': + jtm->tm_mday = atoi(buf); + break; + + /* + * The hour as a decimal number using a 24-hour clock + * (range 00 to 23). + */ + case 'H': + jtm->tm_hour = atoi(buf); + break; + + /* The day of the year as a decimal number (range 001 to 366). */ + case 'j': + jtm->tm_yday = atoi(buf) - 1; + break; + + /* The month as a decimal number (range 01 to 12). */ + case 'm': + jtm->tm_mon = atoi(buf) - 1; + break; + + /* The minute as a decimal number (range 00 to 59). */ + case 'M': + jtm->tm_min = atoi(buf); + break; + + /* Seconds since epoch. (1970/1/1) */ + case 's': + t = (time_t)atol(buf); + jlocaltime_r(&t, &_j); + memcpy(jtm, &_j, sizeof(struct jtm)); + break; + + /* The second as a decimal number (range 00 to 59). */ + case 'S': + jtm->tm_sec = atoi(buf); + break; + + /* + * The year as a decimal number without a century + * (range 00 to 99). + */ + case 'y': + tmp = atoi(buf); + if (tmp >= 19 && tmp < 100) + jtm->tm_year = 1300 + tmp; + else + jtm->tm_year = 1400 + tmp; + break; + + /* The year as a decimal number including the century. */ + case 'Y': + jtm->tm_year = atoi(buf); + break; + + /* The abbreviated or full weekday name. (Farsi) */ + case 'q': + case 'h': + ptr = (fd == 'h') ? (char **)jalali_days_3_fa : (char **)jalali_days_fa; + f = 0; + + for (k = 0; k < J_WEEK_LENGTH; k++) { + if (!strcasecmp(buf, ptr[k])) { + jtm->tm_wday = k; + f = 1; } + } + if (!f) + return (char *)&s[i]; - c++; - j += diff + 2; - i += diff1 + diff; + break; + + default: + break; } - return (char*) &s[s_s]; + c++; + j += diff + 2; + i += diff1 + diff; + } + + return (char *)&s[s_s]; } -char* jasctime_r(const struct jtm* jtm, char* buf) -{ - if (!jtm || !buf) - return 0; +char *jasctime_r(const struct jtm *jtm, char *buf) { + if (!jtm || !buf) + return 0; - in_jasctime(jtm, buf); + in_jasctime(jtm, buf); - return buf; + return buf; } -struct jtm* jlocaltime_r(const time_t* timep, struct jtm* result) -{ - if (!timep || !result) - return 0; +struct jtm *jlocaltime_r(const time_t *timep, struct jtm *result) { + if (!timep || !result) + return 0; - in_jlocaltime(timep, result); + in_jlocaltime(timep, result); - return result; + return result; } -struct jtm* jgmtime_r(const time_t* timep, struct jtm* result) -{ - if (!timep || !result) - return 0; +struct jtm *jgmtime_r(const time_t *timep, struct jtm *result) { + if (!timep || !result) + return 0; - in_jgmtime(timep, result); + in_jgmtime(timep, result); - return result; + return result; } -char* jctime_r(const time_t* timep, char* buf) -{ - if (!timep || !buf) - return 0; +char *jctime_r(const time_t *timep, char *buf) { + if (!timep || !buf) + return 0; - in_jctime(timep, buf); + in_jctime(timep, buf); - return buf; + return buf; } /* @@ -884,41 +853,38 @@ char* jctime_r(const time_t* timep, char* buf) * jalali_to_farsi() converts an integer's digits to Arabic-Indic * padding works just like printf() field width. */ -int jalali_to_farsi(char* buf, - size_t n, - int padding, - char* pad, - int d) -{ - char _buf[100] = {0}; - int i=0, j=0; - int p = 0; - int c = 0; - int cw = (pad[0] < 0) ? 2 : 1; - - for (i=d; i!=0; c++, - _buf[p] = farsi_digits[i%10 > 0 ? i%10 : -(i%10)][1], - _buf[p+1] = farsi_digits[i%10 > 0 ? i%10 : -(i%10)][0], - i/=10, - p+=2); - - if (d < 0) { - _buf[p] = '-'; - c++; - p++; - } - - _buf[p]= 0; - buf[0] = 0; - i=0; - - for (i=0; (i<(padding - c)) && (i*cw < (int)(n-1)); - strcat(buf, pad), i++); - buf[i*cw] = 0; - - for (j=0, i*=cw; (j 0 ? i % 10 : -(i % 10)][1], + _buf[p + 1] = farsi_digits[i % 10 > 0 ? i % 10 : -(i % 10)][0], i /= 10, + p += 2) + ; + + if (d < 0) { + _buf[p] = '-'; + c++; + p++; + } + + _buf[p] = 0; + buf[0] = 0; + i = 0; + + for (i = 0; (i < (padding - c)) && (i * cw < (int)(n - 1)); + strcat(buf, pad), i++) + ; + buf[i * cw] = 0; + + for (j = 0, i *= cw; (j < p) && (i < (int)(n - 1)); + buf[i] = _buf[p - j - 1], i++, j++) + ; + buf[i] = 0; + + return i; } diff --git a/sources/libjalali/jtime.h b/sources/libjalali/jtime.h index fd658f1..6f8baaf 100644 --- a/sources/libjalali/jtime.h +++ b/sources/libjalali/jtime.h @@ -31,30 +31,30 @@ extern "C" { #define MAX_BUF_SIZE 2048 -extern char* jasctime(const struct jtm* jtm); +extern char *jasctime(const struct jtm *jtm); -extern char* jctime(const time_t* timep); +extern char *jctime(const time_t *timep); -extern struct jtm* jgmtime(const time_t* timep); +extern struct jtm *jgmtime(const time_t *timep); -extern struct jtm* jlocaltime(const time_t* timep); +extern struct jtm *jlocaltime(const time_t *timep); -extern time_t jmktime(struct jtm* jtm); +extern time_t jmktime(struct jtm *jtm); -extern size_t jstrftime(char* s, size_t max, const char* format, - const struct jtm* jtm); +extern size_t jstrftime(char *s, size_t max, const char *format, + const struct jtm *jtm); -extern char* jstrptime(const char* s, const char* format, struct jtm* jtm); +extern char *jstrptime(const char *s, const char *format, struct jtm *jtm); -extern char* jasctime_r(const struct jtm* jtm, char* buf); +extern char *jasctime_r(const struct jtm *jtm, char *buf); -extern char* jctime_r(const time_t* timep, char* buf); +extern char *jctime_r(const time_t *timep, char *buf); -extern struct jtm* jgmtime_r(const time_t* timep, struct jtm* result); +extern struct jtm *jgmtime_r(const time_t *timep, struct jtm *result); -extern struct jtm* jlocaltime_r(const time_t* timep, struct jtm* result); +extern struct jtm *jlocaltime_r(const time_t *timep, struct jtm *result); -extern int jalali_to_farsi(char* buf, size_t n, int padding, char* pad, int d); +extern int jalali_to_farsi(char *buf, size_t n, int padding, char *pad, int d); #ifdef __cplusplus }