00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "config.h"
00039 #include <stdio.h>
00040 #include <ctype.h>
00041 #include <sys/time.h>
00042 #include <time.h>
00043 #include <wchar.h>
00044 #include <limits.h>
00045 #include <stdlib.h>
00046 #include <string.h>
00047 #include <glib.h>
00048 #include "qof.h"
00049 #include "qofdate-p.h"
00050
00051 static QofLogModule log_module = QOF_MOD_DATE;
00052
00053 #define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len))
00054 #define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len))
00055
00056 #define FPRINTFTIME 0
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #define SHR(a, b) \
00069 (-1 >> 1 == -1 \
00070 ? (a) >> (b) \
00071 : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
00072
00073
00074
00075
00076
00077 #define INT_strlen _BOUND(t) \
00078 ((sizeof (t) * CHAR_BIT - 1) * 146 / 485 + 2)
00079
00080
00081
00082 #define TM_YEAR_BASE 0
00083
00084 #define add(n, f) \
00085 do \
00086 { \
00087 gint _n = (n); \
00088 gint _delta = width - _n; \
00089 gint _incr = _n + (_delta > 0 ? _delta : 0); \
00090 if ((size_t) _incr >= maxsize - i) \
00091 return 0; \
00092 if (p) \
00093 { \
00094 if (digits == 0 && _delta > 0) \
00095 { \
00096 if (pad == ('0')) \
00097 memset_zero (p, _delta); \
00098 else \
00099 memset_space (p, _delta); \
00100 } \
00101 f; \
00102 p += FPRINTFTIME ? 0 : _n; \
00103 } \
00104 i += _incr; \
00105 } while (0)
00106
00107 # define add1(C) add (1, *p = C)
00108
00109 # define cpy(n, s) \
00110 add ((n), \
00111 if (to_lowcase) \
00112 memcpy_lowcase (p, (s), _n); \
00113 else if (to_uppcase) \
00114 memcpy_uppcase (p, (s), _n); \
00115 else \
00116 memcpy ((void *) p, (void const *) (s), _n))
00117
00118 #define TOUPPER(Ch, L) (islower (Ch) ? toupper (Ch) : (Ch))
00119 #define TOLOWER(Ch, L) (isupper (Ch) ? tolower (Ch) : (Ch))
00120
00121
00122
00123
00124
00125 #define ISDIGIT(Ch) ((guint) (Ch) - ('0') <= 9)
00126
00127
00128
00129
00130 #define ISO_WEEK_START_WDAY 1
00131 #define ISO_WEEK1_WDAY 4
00132 #define YDAY_MINIMUM (-366)
00133
00134 static const mbstate_t mbstate_zero;
00135 const gchar *format_end = NULL;
00136
00137 static gchar *
00138 memcpy_lowcase (gchar * dest, const gchar * src, size_t len)
00139 {
00140 while (len-- > 0)
00141 dest[len] = TOLOWER ((guchar) src[len], loc);
00142 return dest;
00143 }
00144
00145 static gchar *
00146 memcpy_uppcase (gchar * dest, const gchar * src, size_t len)
00147 {
00148 while (len-- > 0)
00149 dest[len] = TOUPPER ((guchar) src[len], loc);
00150 return dest;
00151 }
00152
00153 static gint
00154 iso_week_days (gint yday, gint wday)
00155 {
00156
00157 gint big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
00158 return (yday
00159 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
00160 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
00161 }
00162
00163 size_t
00164 strftime_case (gboolean upcase, gchar * s,
00165 size_t maxsize, const gchar *format, const QofDate *qd,
00166 gint ut, glong ns)
00167 {
00168 const gchar *zone;
00169 gint hour12 = qd->qd_hour;
00170 size_t i = 0;
00171 gchar *p = s;
00172 const gchar *f;
00173 QofDate copy = *qd;
00174 qd = ©
00175 zone = (const gchar *) qd->qd_zone;
00176 if (ut)
00177 {
00178 if (!(zone && *zone))
00179 {
00180 setenv ("TZ", "GMT", 1);
00181 zone = "GMT";
00182 }
00183 }
00184 else
00185 {
00186
00187
00188 tzset ();
00189 }
00190
00191 if (hour12 > 12)
00192 hour12 -= 12;
00193 else if (hour12 == 0)
00194 hour12 = 12;
00195
00196 for (f = format; *f != '\0'; ++f)
00197 {
00198 gint pad = 0;
00199 gint modifier;
00200 gint digits = 0;
00201 glong number_value;
00202 guint u_number_value;
00203 gboolean negative_number;
00204 gboolean always_output_a_sign;
00205 gint tz_colon_mask;
00206 const gchar *subfmt;
00207 gchar sign_char;
00208 gchar *bufp;
00209 gchar buf[MAX_DATE_BUFFER];
00210 gint width = -1;
00211 gboolean to_lowcase = FALSE;
00212 gboolean to_uppcase = upcase;
00213 size_t colons;
00214 gboolean change_case = FALSE;
00215 gint format_char;
00216
00217 switch (*f)
00218 {
00219 case ('%'):
00220 break;
00221
00222 case ('\b'):
00223 case ('\t'):
00224 case ('\n'):
00225 case ('\v'):
00226 case ('\f'):
00227 case ('\r'):
00228 case (' '):
00229 case ('!'):
00230 case ('"'):
00231 case ('#'):
00232 case ('&'):
00233 case ('\''):
00234 case ('('):
00235 case (')'):
00236 case ('*'):
00237 case ('+'):
00238 case (','):
00239 case ('-'):
00240 case ('.'):
00241 case ('/'):
00242 case ('0'):
00243 case ('1'):
00244 case ('2'):
00245 case ('3'):
00246 case ('4'):
00247 case ('5'):
00248 case ('6'):
00249 case ('7'):
00250 case ('8'):
00251 case ('9'):
00252 case (':'):
00253 case (';'):
00254 case ('<'):
00255 case ('='):
00256 case ('>'):
00257 case ('?'):
00258 case ('A'):
00259 case ('B'):
00260 case ('C'):
00261 case ('D'):
00262 case ('E'):
00263 case ('F'):
00264 case ('G'):
00265 case ('H'):
00266 case ('I'):
00267 case ('J'):
00268 case ('K'):
00269 case ('L'):
00270 case ('M'):
00271 case ('N'):
00272 case ('O'):
00273 case ('P'):
00274 case ('Q'):
00275 case ('R'):
00276 case ('S'):
00277 case ('T'):
00278 case ('U'):
00279 case ('V'):
00280 case ('W'):
00281 case ('X'):
00282 case ('Y'):
00283 case ('Z'):
00284 case ('['):
00285 case ('\\'):
00286 case (']'):
00287 case ('^'):
00288 case ('_'):
00289 case ('a'):
00290 case ('b'):
00291 case ('c'):
00292 case ('d'):
00293 case ('e'):
00294 case ('f'):
00295 case ('g'):
00296 case ('h'):
00297 case ('i'):
00298 case ('j'):
00299 case ('k'):
00300 case ('l'):
00301 case ('m'):
00302 case ('n'):
00303 case ('o'):
00304 case ('p'):
00305 case ('q'):
00306 case ('r'):
00307 case ('s'):
00308 case ('t'):
00309 case ('u'):
00310 case ('v'):
00311 case ('w'):
00312 case ('x'):
00313 case ('y'):
00314 case ('z'):
00315 case ('{'):
00316 case ('|'):
00317 case ('}'):
00318 case ('~'):
00319
00320
00321
00322
00323 add1 (*f);
00324 continue;
00325
00326 default:
00327
00328
00329
00330 {
00331 mbstate_t mbstate = mbstate_zero;
00332 size_t len = 0;
00333 size_t fsize;
00334
00335 if (!format_end)
00336 format_end = f + strlen (f) + 1;
00337 fsize = format_end - f;
00338
00339 do
00340 {
00341 size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
00342
00343 if (bytes == 0)
00344 break;
00345
00346 if (bytes == (size_t) - 2)
00347 {
00348 len += strlen (f + len);
00349 break;
00350 }
00351
00352 if (bytes == (size_t) - 1)
00353 {
00354 len++;
00355 break;
00356 }
00357
00358 len += bytes;
00359 }
00360 while (!mbsinit (&mbstate));
00361
00362 cpy (len, f);
00363 f += len - 1;
00364 continue;
00365 }
00366 }
00367
00368
00369 while (1)
00370 {
00371 switch (*++f)
00372 {
00373
00374 case ('_'):
00375 case ('-'):
00376 case ('0'):
00377 pad = *f;
00378 continue;
00379
00380
00381 case ('^'):
00382 to_uppcase = TRUE;
00383 continue;
00384 case ('#'):
00385 change_case = TRUE;
00386 continue;
00387
00388 default:
00389 break;
00390 }
00391 break;
00392 }
00393
00394
00395 if (ISDIGIT (*f))
00396 {
00397 width = 0;
00398 do
00399 {
00400 if (width > INT_MAX / 10
00401 || (width == INT_MAX / 10
00402 && *f - ('0') > INT_MAX % 10))
00403
00404 width = INT_MAX;
00405 else
00406 {
00407 width *= 10;
00408 width += *f - ('0');
00409 }
00410 ++f;
00411 }
00412 while (ISDIGIT (*f));
00413 }
00414
00415
00416 switch (*f)
00417 {
00418 case ('E'):
00419 case ('O'):
00420 modifier = *f++;
00421 break;
00422
00423 default:
00424 modifier = 0;
00425 break;
00426 }
00427
00428
00429 format_char = *f;
00430 switch (format_char)
00431 {
00432 #define DO_NUMBER(d, v) \
00433 digits = d; \
00434 number_value = v; goto do_number
00435 #define DO_SIGNED_NUMBER(d, negative, v) \
00436 digits = d; \
00437 negative_number = negative; \
00438 u_number_value = v; goto do_signed_number
00439
00440
00441
00442
00443 #define DO_TZ_OFFSET(d, negative, mask, v) \
00444 digits = d; \
00445 negative_number = negative; \
00446 tz_colon_mask = mask; \
00447 u_number_value = v; goto do_tz_offset
00448 #define DO_NUMBER_SPACEPAD(d, v) \
00449 digits = d; \
00450 number_value = v; goto do_number_spacepad
00451
00452 case ('%'):
00453 if (modifier != 0)
00454 goto bad_format;
00455 add1 (*f);
00456 break;
00457
00458 case ('a'):
00459 if (modifier != 0)
00460 goto bad_format;
00461 if (change_case)
00462 {
00463 to_uppcase = TRUE;
00464 to_lowcase = FALSE;
00465 }
00466 goto underlying_strftime;
00467
00468 case 'A':
00469 if (modifier != 0)
00470 goto bad_format;
00471 if (change_case)
00472 {
00473 to_uppcase = TRUE;
00474 to_lowcase = FALSE;
00475 }
00476 goto underlying_strftime;
00477
00478 case ('b'):
00479 case ('h'):
00480 if (change_case)
00481 {
00482 to_uppcase = TRUE;
00483 to_lowcase = FALSE;
00484 }
00485 if (modifier != 0)
00486 goto bad_format;
00487 goto underlying_strftime;
00488
00489 case ('B'):
00490 if (modifier != 0)
00491 goto bad_format;
00492 if (change_case)
00493 {
00494 to_uppcase = TRUE;
00495 to_lowcase = FALSE;
00496 }
00497 goto underlying_strftime;
00498
00499 case ('c'):
00500 if (modifier == ('O'))
00501 goto bad_format;
00502 goto underlying_strftime;
00503
00504 subformat:
00505 {
00506 size_t len = strftime_case (to_uppcase,
00507 NULL, ((size_t) - 1),
00508 subfmt, qd, ut, ns);
00509 add (len, strftime_case (to_uppcase, p,
00510 (maxsize - i), subfmt, qd, ut, ns));
00511 }
00512 break;
00513
00514 underlying_strftime:
00515 {
00516
00517 gchar ufmt[5];
00518 gchar *u = ufmt;
00519 gchar ubuf[1024];
00520 size_t len;
00521
00522
00523
00524 # ifdef strftime
00525 # undef strftime
00526 size_t strftime ();
00527 #endif
00528
00529
00530
00531 *u++ = ' ';
00532 *u++ = '%';
00533 if (modifier != 0)
00534 *u++ = modifier;
00535 *u++ = format_char;
00536 *u = '\0';
00537 {
00538 glong nanosecs;
00539 struct tm bad;
00540 if(!qof_date_to_struct_tm ((QofDate*)qd, &bad, &nanosecs))
00541 {
00542 PERR (" locale format out of range.");
00543 break;
00544 }
00545 len = strftime (ubuf, sizeof ubuf, ufmt, &bad);
00546 }
00547 if (len != 0)
00548 cpy (len - 1, ubuf + 1);
00549 }
00550 break;
00551
00552 case ('C'):
00553 if (modifier == ('O'))
00554 goto bad_format;
00555 if (modifier == ('E'))
00556 {
00557 goto underlying_strftime;
00558 }
00559
00560 {
00561
00562 gint century = qd->qd_year / 100 + TM_YEAR_BASE / 100;
00563 century -= qd->qd_year % 100 < 0 && 0 < century;
00564 DO_SIGNED_NUMBER (2,
00565 qd->qd_year < -TM_YEAR_BASE, century);
00566 }
00567
00568 case ('x'):
00569 if (modifier == ('O'))
00570 goto bad_format;
00571 goto underlying_strftime;
00572 case ('D'):
00573 if (modifier != 0)
00574 goto bad_format;
00575 subfmt = ("%m/%d/%y");
00576 goto subformat;
00577
00578 case ('d'):
00579 if (modifier == ('E'))
00580 goto bad_format;
00581
00582 DO_NUMBER (2, qd->qd_mday);
00583
00584 case ('e'):
00585 if (modifier == ('E'))
00586 goto bad_format;
00587
00588 DO_NUMBER_SPACEPAD (2, qd->qd_mday);
00589
00590
00591
00592 do_tz_offset:
00593 always_output_a_sign = TRUE;
00594 goto do_number_body;
00595
00596 do_number_spacepad:
00597
00598 if (pad != ('0') && pad != ('-'))
00599 pad = ('_');
00600
00601 do_number:
00602
00603 negative_number = number_value < 0;
00604 u_number_value = number_value;
00605
00606 do_signed_number:
00607 always_output_a_sign = FALSE;
00608 tz_colon_mask = 0;
00609
00610 do_number_body:
00611
00612
00613
00614
00615
00616 if (modifier == ('O') && !negative_number)
00617 {
00618 goto underlying_strftime;
00619 }
00620
00621 bufp = buf + sizeof (buf) / sizeof (buf[0]);
00622
00623 if (negative_number)
00624 u_number_value = -u_number_value;
00625
00626 do
00627 {
00628 if (tz_colon_mask & 1)
00629 *--bufp = ':';
00630 tz_colon_mask >>= 1;
00631 *--bufp = u_number_value % 10 + ('0');
00632 u_number_value /= 10;
00633 }
00634 while (u_number_value != 0 || tz_colon_mask != 0);
00635
00636 do_number_sign_and_padding:
00637 if (digits < width)
00638 digits = width;
00639
00640 sign_char = (negative_number ? ('-')
00641 : always_output_a_sign ? ('+') : 0);
00642
00643 if (pad == ('-'))
00644 {
00645 if (sign_char)
00646 add1 (sign_char);
00647 }
00648 else
00649 {
00650 gint padding =
00651 digits - (buf + (sizeof (buf) / sizeof (buf[0])) -
00652 bufp) - !!sign_char;
00653
00654 if (padding > 0)
00655 {
00656 if (pad == ('_'))
00657 {
00658 if ((size_t) padding >= maxsize - i)
00659 return 0;
00660
00661 if (p)
00662 memset_space (p, padding);
00663 i += padding;
00664 width = width > padding ? width - padding : 0;
00665 if (sign_char)
00666 add1 (sign_char);
00667 }
00668 else
00669 {
00670 if ((size_t) digits >= maxsize - i)
00671 return 0;
00672
00673 if (sign_char)
00674 add1 (sign_char);
00675
00676 if (p)
00677 memset_zero (p, padding);
00678 i += padding;
00679 width = 0;
00680 }
00681 }
00682 else
00683 {
00684 if (sign_char)
00685 add1 (sign_char);
00686 }
00687 }
00688
00689 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
00690 break;
00691
00692 case ('F'):
00693 if (modifier != 0)
00694 goto bad_format;
00695 subfmt = ("%Y-%m-%d");
00696 goto subformat;
00697
00698 case ('H'):
00699 if (modifier == ('E'))
00700 goto bad_format;
00701
00702 DO_NUMBER (2, qd->qd_hour);
00703
00704 case ('I'):
00705 if (modifier == ('E'))
00706 goto bad_format;
00707
00708 DO_NUMBER (2, hour12);
00709
00710 case ('k'):
00711 if (modifier == ('E'))
00712 goto bad_format;
00713
00714 DO_NUMBER_SPACEPAD (2, qd->qd_hour);
00715
00716 case ('l'):
00717 if (modifier == ('E'))
00718 goto bad_format;
00719
00720 DO_NUMBER_SPACEPAD (2, hour12);
00721
00722 case ('j'):
00723 if (modifier == ('E'))
00724 goto bad_format;
00725
00726 DO_SIGNED_NUMBER (3, qd->qd_yday < -1, qd->qd_yday + 1U);
00727
00728 case ('M'):
00729 if (modifier == ('E'))
00730 goto bad_format;
00731
00732 DO_NUMBER (2, qd->qd_min);
00733
00734 case ('m'):
00735 if (modifier == ('E'))
00736 goto bad_format;
00737
00738 DO_SIGNED_NUMBER (2, qd->qd_mon < -1, qd->qd_mon);
00739
00740 case ('N'):
00741 if (modifier == ('E'))
00742 goto bad_format;
00743
00744 number_value = ns;
00745 if (width == -1)
00746 width = 9;
00747 else
00748 {
00749
00750 gint j;
00751 for (j = width; j < 9; j++)
00752 number_value /= 10;
00753 }
00754
00755 DO_NUMBER (width, number_value);
00756
00757 case ('n'):
00758 add1 (('\n'));
00759 break;
00760
00761 case ('P'):
00762 to_lowcase = TRUE;
00763 format_char = ('p');
00764
00765 case ('p'):
00766 if (change_case)
00767 {
00768 to_uppcase = FALSE;
00769 to_lowcase = TRUE;
00770 }
00771 goto underlying_strftime;
00772
00773 case ('R'):
00774 subfmt = ("%H:%M");
00775 goto subformat;
00776
00777 case ('r'):
00778 goto underlying_strftime;
00779
00780 case ('S'):
00781 if (modifier == ('E'))
00782 goto bad_format;
00783
00784 DO_NUMBER (2, qd->qd_sec);
00785
00786 case ('s'):
00787
00788
00789
00790 {
00791 glong nanosecs;
00792 QofTime *time;
00793 QofTimeSecs t;
00794
00795 time = qof_date_to_qtime ((QofDate*)qd);
00796 t = qof_time_get_secs (time);
00797 nanosecs = qof_time_get_nanosecs (time);
00798
00799
00800
00801
00802 bufp = buf + sizeof (buf) / sizeof (buf[0]);
00803 negative_number = t < 0;
00804
00805 do
00806 {
00807 gint d = t % 10;
00808 t /= 10;
00809 *--bufp = (negative_number ? -d : d) + ('0');
00810 }
00811 while (t != 0);
00812
00813 digits = 1;
00814 always_output_a_sign = FALSE;
00815 goto do_number_sign_and_padding;
00816 }
00817
00818 case ('X'):
00819 if (modifier == ('O'))
00820 goto bad_format;
00821 goto underlying_strftime;
00822 case ('T'):
00823 subfmt = ("%H:%M:%S");
00824 goto subformat;
00825
00826 case ('t'):
00827 add1 (('\t'));
00828 break;
00829
00830 case ('u'):
00831 DO_NUMBER (1, (qd->qd_wday - 1 + 7) % 7 + 1);
00832
00833 case ('U'):
00834 if (modifier == ('E'))
00835 goto bad_format;
00836
00837 DO_NUMBER (2, (qd->qd_yday - qd->qd_wday + 7) / 7);
00838
00839 case ('V'):
00840 case ('g'):
00841 case ('G'):
00842 if (modifier == ('E'))
00843 goto bad_format;
00844 {
00845 gint year_adjust = 0;
00846 gint days = iso_week_days (qd->qd_yday, qd->qd_wday);
00847
00848 if (days < 0)
00849 {
00850
00851 year_adjust = -1;
00852 days =
00853 iso_week_days (qd->qd_yday +
00854 (365 + qof_date_isleap (qd->qd_year - 1)),
00855 qd->qd_wday);
00856 }
00857 else
00858 {
00859 gint d =
00860 iso_week_days (qd->qd_yday - (365 +
00861 qof_date_isleap (qd->qd_year)),
00862 qd->qd_wday);
00863 if (0 <= d)
00864 {
00865
00866 year_adjust = 1;
00867 days = d;
00868 }
00869 }
00870
00871 switch (*f)
00872 {
00873 case ('g'):
00874 {
00875
00876 gint yy = (qd->qd_year % 100 + year_adjust) % 100;
00877 DO_NUMBER (2, (0 <= yy
00878 ? yy : qd->qd_year <
00879 -TM_YEAR_BASE -
00880 year_adjust ? -yy : yy + 100));
00881 }
00882
00883 case ('G'):
00884
00885 DO_SIGNED_NUMBER (4,
00886 qd->qd_year <
00887 -TM_YEAR_BASE - year_adjust,
00888 (qd->qd_year + (guint) TM_YEAR_BASE +
00889 year_adjust));
00890
00891 default:
00892 DO_NUMBER (2, days / 7 + 1);
00893 }
00894 }
00895
00896 case ('W'):
00897 if (modifier == ('E'))
00898 goto bad_format;
00899
00900 DO_NUMBER (2,
00901 (qd->qd_yday - (qd->qd_wday - 1 + 7) % 7 + 7) / 7);
00902
00903 case ('w'):
00904 if (modifier == ('E'))
00905 goto bad_format;
00906
00907 DO_NUMBER (1, qd->qd_wday);
00908
00909 case ('Y'):
00910 if (modifier == 'E')
00911 {
00912 goto underlying_strftime;
00913 }
00914 if (modifier == ('O'))
00915 goto bad_format;
00916 else
00917
00918 DO_SIGNED_NUMBER (4, qd->qd_year < -TM_YEAR_BASE,
00919 qd->qd_year + TM_YEAR_BASE);
00920
00921 case ('y'):
00922 if (modifier == ('E'))
00923 {
00924 goto underlying_strftime;
00925 }
00926
00927 {
00928 gint64 yy = qd->qd_year % 100;
00929 if (yy < 0)
00930 yy = qd->qd_year < -TM_YEAR_BASE ? -yy : yy + 100;
00931 DO_NUMBER (2, yy);
00932 }
00933
00934 case ('Z'):
00935 if (change_case)
00936 {
00937 to_uppcase = FALSE;
00938 to_lowcase = TRUE;
00939 }
00940
00941
00942 if (!(zone && *zone) && qd->qd_is_dst >= 0)
00943 zone = tzname[qd->qd_is_dst != 0];
00944 if (!zone)
00945 zone = "";
00946
00947 cpy (strlen (zone), zone);
00948 break;
00949
00950 case (':'):
00951
00952
00953 for (colons = 1; f[colons] == (':'); colons++)
00954 continue;
00955 if (f[colons] != ('z'))
00956 goto bad_format;
00957 f += colons;
00958 goto do_z_conversion;
00959
00960 case ('z'):
00961 colons = 0;
00962
00963 do_z_conversion:
00964 if (qd->qd_is_dst < 0)
00965 break;
00966
00967 {
00968 gint diff;
00969 gint hour_diff;
00970 gint min_diff;
00971 gint sec_diff;
00972 diff = qd->qd_gmt_off;
00973 hour_diff = diff / 60 / 60;
00974 min_diff = diff / 60 % 60;
00975 sec_diff = diff % 60;
00976
00977 switch (colons)
00978 {
00979 case 0:
00980 DO_TZ_OFFSET (5, diff < 0, 0,
00981 hour_diff * 100 + min_diff);
00982
00983 case 1:
00984 tz_hh_mm:
00985 DO_TZ_OFFSET (6, diff < 0, 04,
00986 hour_diff * 100 + min_diff);
00987
00988 case 2:
00989 tz_hh_mm_ss:
00990 DO_TZ_OFFSET (9, diff < 0, 024,
00991 hour_diff * 10000 + min_diff * 100 + sec_diff);
00992
00993 case 3:
00994 if (sec_diff != 0)
00995 goto tz_hh_mm_ss;
00996 if (min_diff != 0)
00997 goto tz_hh_mm;
00998 DO_TZ_OFFSET (3, diff < 0, 0, hour_diff);
00999
01000 default:
01001 goto bad_format;
01002 }
01003 }
01004
01005 case ('\0'):
01006 --f;
01007
01008 default:
01009
01010
01011
01012 bad_format:
01013 {
01014 gint flen;
01015 for (flen = 1; f[1 - flen] != ('%'); flen++)
01016 continue;
01017 cpy (flen, &f[1 - flen]);
01018 }
01019 break;
01020 }
01021 }
01022 return i;
01023 }