LCOV - code coverage report
Current view: top level - src/timezone - strftime.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 30.2 % 232 70
Test Date: 2026-03-03 17:14:48 Functions: 100.0 % 5 5
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Convert a broken-down timestamp to a string.  */
       2              : 
       3              : /*
       4              :  * Copyright 1989 The Regents of the University of California.
       5              :  * All rights reserved.
       6              :  *
       7              :  * Redistribution and use in source and binary forms, with or without
       8              :  * modification, are permitted provided that the following conditions
       9              :  * are met:
      10              :  * 1. Redistributions of source code must retain the above copyright
      11              :  *    notice, this list of conditions and the following disclaimer.
      12              :  * 2. Redistributions in binary form must reproduce the above copyright
      13              :  *    notice, this list of conditions and the following disclaimer in the
      14              :  *    documentation and/or other materials provided with the distribution.
      15              :  * 3. Neither the name of the University nor the names of its contributors
      16              :  *    may be used to endorse or promote products derived from this software
      17              :  *    without specific prior written permission.
      18              :  *
      19              :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
      20              :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      21              :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      22              :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      23              :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      24              :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      25              :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      26              :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      27              :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      28              :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      29              :  * SUCH DAMAGE.
      30              :  */
      31              : 
      32              : /*
      33              :  * Based on the UCB version with the copyright notice appearing above.
      34              :  *
      35              :  * This is ANSIish only when "multibyte character == plain character".
      36              :  *
      37              :  * IDENTIFICATION
      38              :  *    src/timezone/strftime.c
      39              :  */
      40              : 
      41              : #include "postgres.h"
      42              : 
      43              : #include <fcntl.h>
      44              : 
      45              : #include "private.h"
      46              : 
      47              : 
      48              : struct lc_time_T
      49              : {
      50              :     const char *mon[MONSPERYEAR];
      51              :     const char *month[MONSPERYEAR];
      52              :     const char *wday[DAYSPERWEEK];
      53              :     const char *weekday[DAYSPERWEEK];
      54              :     const char *X_fmt;
      55              :     const char *x_fmt;
      56              :     const char *c_fmt;
      57              :     const char *am;
      58              :     const char *pm;
      59              :     const char *date_fmt;
      60              : };
      61              : 
      62              : #define Locale  (&C_time_locale)
      63              : 
      64              : static const struct lc_time_T C_time_locale = {
      65              :     {
      66              :         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
      67              :         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
      68              :     }, {
      69              :         "January", "February", "March", "April", "May", "June",
      70              :         "July", "August", "September", "October", "November", "December"
      71              :     }, {
      72              :         "Sun", "Mon", "Tue", "Wed",
      73              :         "Thu", "Fri", "Sat"
      74              :     }, {
      75              :         "Sunday", "Monday", "Tuesday", "Wednesday",
      76              :         "Thursday", "Friday", "Saturday"
      77              :     },
      78              : 
      79              :     /* X_fmt */
      80              :     "%H:%M:%S",
      81              : 
      82              :     /*
      83              :      * x_fmt
      84              :      *
      85              :      * C99 and later require this format. Using just numbers (as here) makes
      86              :      * Quakers happier; it's also compatible with SVR4.
      87              :      */
      88              :     "%m/%d/%y",
      89              : 
      90              :     /*
      91              :      * c_fmt
      92              :      *
      93              :      * C99 and later require this format. Previously this code used "%D %X",
      94              :      * but we now conform to C99. Note that "%a %b %d %H:%M:%S %Y" is used by
      95              :      * Solaris 2.3.
      96              :      */
      97              :     "%a %b %e %T %Y",
      98              : 
      99              :     /* am */
     100              :     "AM",
     101              : 
     102              :     /* pm */
     103              :     "PM",
     104              : 
     105              :     /* date_fmt */
     106              :     "%a %b %e %H:%M:%S %Z %Y"
     107              : };
     108              : 
     109              : enum warn
     110              : {
     111              :     IN_NONE, IN_SOME, IN_THIS, IN_ALL
     112              : };
     113              : 
     114              : static char *_add(const char *str, char *pt, const char *ptlim);
     115              : static char *_conv(int n, const char *format, char *pt, const char *ptlim);
     116              : static char *_fmt(const char *format, const struct pg_tm *t, char *pt, const char *ptlim,
     117              :                   enum warn *warnp);
     118              : static char *_yconv(int a, int b, bool convert_top, bool convert_yy, char *pt, char const *ptlim);
     119              : 
     120              : 
     121              : /*
     122              :  * Convert timestamp t to string s, a caller-allocated buffer of size maxsize,
     123              :  * using the given format pattern.
     124              :  *
     125              :  * See also timestamptz_to_str.
     126              :  */
     127              : size_t
     128       904726 : pg_strftime(char *s, size_t maxsize, const char *format, const struct pg_tm *t)
     129              : {
     130              :     char       *p;
     131       904726 :     int         saved_errno = errno;
     132       904726 :     enum warn   warn = IN_NONE;
     133              : 
     134       904726 :     p = _fmt(format, t, s, s + maxsize, &warn);
     135       904726 :     if (!p)
     136              :     {
     137            0 :         errno = EOVERFLOW;
     138            0 :         return 0;
     139              :     }
     140       904726 :     if (p == s + maxsize)
     141              :     {
     142            0 :         errno = ERANGE;
     143            0 :         return 0;
     144              :     }
     145       904726 :     *p = '\0';
     146       904726 :     errno = saved_errno;
     147       904726 :     return p - s;
     148              : }
     149              : 
     150              : static char *
     151       904726 : _fmt(const char *format, const struct pg_tm *t, char *pt,
     152              :      const char *ptlim, enum warn *warnp)
     153              : {
     154     15619319 :     for (; *format; ++format)
     155              :     {
     156     14714593 :         if (*format == '%')
     157              :         {
     158      6334673 :     label:
     159      6334673 :             switch (*++format)
     160              :             {
     161            0 :                 case '\0':
     162            0 :                     --format;
     163            0 :                     break;
     164            0 :                 case 'A':
     165            0 :                     pt = _add((t->tm_wday < 0 ||
     166            0 :                                t->tm_wday >= DAYSPERWEEK) ?
     167            0 :                               "?" : Locale->weekday[t->tm_wday],
     168              :                               pt, ptlim);
     169            0 :                     continue;
     170          800 :                 case 'a':
     171         1600 :                     pt = _add((t->tm_wday < 0 ||
     172          800 :                                t->tm_wday >= DAYSPERWEEK) ?
     173          800 :                               "?" : Locale->wday[t->tm_wday],
     174              :                               pt, ptlim);
     175          800 :                     continue;
     176            0 :                 case 'B':
     177            0 :                     pt = _add((t->tm_mon < 0 ||
     178            0 :                                t->tm_mon >= MONSPERYEAR) ?
     179            0 :                               "?" : Locale->month[t->tm_mon],
     180              :                               pt, ptlim);
     181            0 :                     continue;
     182          800 :                 case 'b':
     183              :                 case 'h':
     184         1600 :                     pt = _add((t->tm_mon < 0 ||
     185          800 :                                t->tm_mon >= MONSPERYEAR) ?
     186          800 :                               "?" : Locale->mon[t->tm_mon],
     187              :                               pt, ptlim);
     188          800 :                     continue;
     189            0 :                 case 'C':
     190              : 
     191              :                     /*
     192              :                      * %C used to do a... _fmt("%a %b %e %X %Y", t);
     193              :                      * ...whereas now POSIX 1003.2 calls for something
     194              :                      * completely different. (ado, 1993-05-24)
     195              :                      */
     196            0 :                     pt = _yconv(t->tm_year, TM_YEAR_BASE,
     197              :                                 true, false, pt, ptlim);
     198            0 :                     continue;
     199            0 :                 case 'c':
     200              :                     {
     201            0 :                         enum warn   warn2 = IN_SOME;
     202              : 
     203            0 :                         pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
     204            0 :                         if (warn2 == IN_ALL)
     205            0 :                             warn2 = IN_THIS;
     206            0 :                         if (warn2 > *warnp)
     207            0 :                             *warnp = warn2;
     208              :                     }
     209            0 :                     continue;
     210            0 :                 case 'D':
     211            0 :                     pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);
     212            0 :                     continue;
     213       904726 :                 case 'd':
     214       904726 :                     pt = _conv(t->tm_mday, "%02d", pt, ptlim);
     215       904726 :                     continue;
     216            0 :                 case 'E':
     217              :                 case 'O':
     218              : 
     219              :                     /*
     220              :                      * Locale modifiers of C99 and later. The sequences %Ec
     221              :                      * %EC %Ex %EX %Ey %EY %Od %oe %OH %OI %Om %OM %OS %Ou %OU
     222              :                      * %OV %Ow %OW %Oy are supposed to provide alternative
     223              :                      * representations.
     224              :                      */
     225            0 :                     goto label;
     226            0 :                 case 'e':
     227            0 :                     pt = _conv(t->tm_mday, "%2d", pt, ptlim);
     228            0 :                     continue;
     229            0 :                 case 'F':
     230            0 :                     pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
     231            0 :                     continue;
     232       904726 :                 case 'H':
     233       904726 :                     pt = _conv(t->tm_hour, "%02d", pt, ptlim);
     234       904726 :                     continue;
     235            0 :                 case 'I':
     236            0 :                     pt = _conv((t->tm_hour % 12) ?
     237            0 :                                (t->tm_hour % 12) : 12,
     238              :                                "%02d", pt, ptlim);
     239            0 :                     continue;
     240            0 :                 case 'j':
     241            0 :                     pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim);
     242            0 :                     continue;
     243            0 :                 case 'k':
     244              : 
     245              :                     /*
     246              :                      * This used to be... _conv(t->tm_hour % 12 ? t->tm_hour %
     247              :                      * 12 : 12, 2, ' '); ...and has been changed to the below
     248              :                      * to match SunOS 4.1.1 and Arnold Robbins' strftime
     249              :                      * version 3.0. That is, "%k" and "%l" have been swapped.
     250              :                      * (ado, 1993-05-24)
     251              :                      */
     252            0 :                     pt = _conv(t->tm_hour, "%2d", pt, ptlim);
     253            0 :                     continue;
     254              : #ifdef KITCHEN_SINK
     255              :                 case 'K':
     256              : 
     257              :                     /*
     258              :                      * After all this time, still unclaimed!
     259              :                      */
     260              :                     pt = _add("kitchen sink", pt, ptlim);
     261              :                     continue;
     262              : #endif                          /* defined KITCHEN_SINK */
     263            0 :                 case 'l':
     264              : 
     265              :                     /*
     266              :                      * This used to be... _conv(t->tm_hour, 2, ' '); ...and
     267              :                      * has been changed to the below to match SunOS 4.1.1 and
     268              :                      * Arnold Robbin's strftime version 3.0. That is, "%k" and
     269              :                      * "%l" have been swapped. (ado, 1993-05-24)
     270              :                      */
     271            0 :                     pt = _conv((t->tm_hour % 12) ?
     272            0 :                                (t->tm_hour % 12) : 12,
     273              :                                "%2d", pt, ptlim);
     274            0 :                     continue;
     275       904726 :                 case 'M':
     276       904726 :                     pt = _conv(t->tm_min, "%02d", pt, ptlim);
     277       904726 :                     continue;
     278       903926 :                 case 'm':
     279       903926 :                     pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim);
     280       903926 :                     continue;
     281            0 :                 case 'n':
     282            0 :                     pt = _add("\n", pt, ptlim);
     283            0 :                     continue;
     284            0 :                 case 'p':
     285            0 :                     pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
     286              :                               Locale->pm :
     287              :                               Locale->am,
     288              :                               pt, ptlim);
     289            0 :                     continue;
     290            0 :                 case 'R':
     291            0 :                     pt = _fmt("%H:%M", t, pt, ptlim, warnp);
     292            0 :                     continue;
     293            0 :                 case 'r':
     294            0 :                     pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp);
     295            0 :                     continue;
     296       904726 :                 case 'S':
     297       904726 :                     pt = _conv(t->tm_sec, "%02d", pt, ptlim);
     298       904726 :                     continue;
     299            0 :                 case 'T':
     300            0 :                     pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp);
     301            0 :                     continue;
     302            0 :                 case 't':
     303            0 :                     pt = _add("\t", pt, ptlim);
     304            0 :                     continue;
     305            0 :                 case 'U':
     306            0 :                     pt = _conv((t->tm_yday + DAYSPERWEEK -
     307            0 :                                 t->tm_wday) / DAYSPERWEEK,
     308              :                                "%02d", pt, ptlim);
     309            0 :                     continue;
     310            0 :                 case 'u':
     311              : 
     312              :                     /*
     313              :                      * From Arnold Robbins' strftime version 3.0: "ISO 8601:
     314              :                      * Weekday as a decimal number [1 (Monday) - 7]" (ado,
     315              :                      * 1993-05-24)
     316              :                      */
     317            0 :                     pt = _conv((t->tm_wday == 0) ?
     318              :                                DAYSPERWEEK : t->tm_wday,
     319              :                                "%d", pt, ptlim);
     320            0 :                     continue;
     321            0 :                 case 'V':       /* ISO 8601 week number */
     322              :                 case 'G':       /* ISO 8601 year (four digits) */
     323              :                 case 'g':       /* ISO 8601 year (two digits) */
     324              : /*
     325              :  * From Arnold Robbins' strftime version 3.0: "the week number of the
     326              :  * year (the first Monday as the first day of week 1) as a decimal number
     327              :  * (01-53)."
     328              :  * (ado, 1993-05-24)
     329              :  *
     330              :  * From <https://www.cl.cam.ac.uk/~mgk25/iso-time.html> by Markus Kuhn:
     331              :  * "Week 01 of a year is per definition the first week which has the
     332              :  * Thursday in this year, which is equivalent to the week which contains
     333              :  * the fourth day of January. In other words, the first week of a new year
     334              :  * is the week which has the majority of its days in the new year. Week 01
     335              :  * might also contain days from the previous year and the week before week
     336              :  * 01 of a year is the last week (52 or 53) of the previous year even if
     337              :  * it contains days from the new year. A week starts with Monday (day 1)
     338              :  * and ends with Sunday (day 7). For example, the first week of the year
     339              :  * 1997 lasts from 1996-12-30 to 1997-01-05..."
     340              :  * (ado, 1996-01-02)
     341              :  */
     342              :                     {
     343              :                         int         year;
     344              :                         int         base;
     345              :                         int         yday;
     346              :                         int         wday;
     347              :                         int         w;
     348              : 
     349            0 :                         year = t->tm_year;
     350            0 :                         base = TM_YEAR_BASE;
     351            0 :                         yday = t->tm_yday;
     352            0 :                         wday = t->tm_wday;
     353              :                         for (;;)
     354            0 :                         {
     355              :                             int         len;
     356              :                             int         bot;
     357              :                             int         top;
     358              : 
     359            0 :                             len = isleap_sum(year, base) ?
     360            0 :                                 DAYSPERLYEAR :
     361              :                                 DAYSPERNYEAR;
     362              : 
     363              :                             /*
     364              :                              * What yday (-3 ... 3) does the ISO year begin
     365              :                              * on?
     366              :                              */
     367            0 :                             bot = ((yday + 11 - wday) %
     368              :                                    DAYSPERWEEK) - 3;
     369              : 
     370              :                             /*
     371              :                              * What yday does the NEXT ISO year begin on?
     372              :                              */
     373            0 :                             top = bot -
     374            0 :                                 (len % DAYSPERWEEK);
     375            0 :                             if (top < -3)
     376            0 :                                 top += DAYSPERWEEK;
     377            0 :                             top += len;
     378            0 :                             if (yday >= top)
     379              :                             {
     380            0 :                                 ++base;
     381            0 :                                 w = 1;
     382            0 :                                 break;
     383              :                             }
     384            0 :                             if (yday >= bot)
     385              :                             {
     386            0 :                                 w = 1 + ((yday - bot) /
     387              :                                          DAYSPERWEEK);
     388            0 :                                 break;
     389              :                             }
     390            0 :                             --base;
     391            0 :                             yday += isleap_sum(year, base) ?
     392            0 :                                 DAYSPERLYEAR :
     393              :                                 DAYSPERNYEAR;
     394              :                         }
     395            0 :                         if (*format == 'V')
     396            0 :                             pt = _conv(w, "%02d",
     397              :                                        pt, ptlim);
     398            0 :                         else if (*format == 'g')
     399              :                         {
     400            0 :                             *warnp = IN_ALL;
     401            0 :                             pt = _yconv(year, base,
     402              :                                         false, true,
     403              :                                         pt, ptlim);
     404              :                         }
     405              :                         else
     406            0 :                             pt = _yconv(year, base,
     407              :                                         true, true,
     408              :                                         pt, ptlim);
     409              :                     }
     410            0 :                     continue;
     411            0 :                 case 'v':
     412              : 
     413              :                     /*
     414              :                      * From Arnold Robbins' strftime version 3.0: "date as
     415              :                      * dd-bbb-YYYY" (ado, 1993-05-24)
     416              :                      */
     417            0 :                     pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp);
     418            0 :                     continue;
     419            0 :                 case 'W':
     420            0 :                     pt = _conv((t->tm_yday + DAYSPERWEEK -
     421            0 :                                 (t->tm_wday ?
     422            0 :                                  (t->tm_wday - 1) :
     423              :                                  (DAYSPERWEEK - 1))) / DAYSPERWEEK,
     424              :                                "%02d", pt, ptlim);
     425            0 :                     continue;
     426            0 :                 case 'w':
     427            0 :                     pt = _conv(t->tm_wday, "%d", pt, ptlim);
     428            0 :                     continue;
     429            0 :                 case 'X':
     430            0 :                     pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp);
     431            0 :                     continue;
     432            0 :                 case 'x':
     433              :                     {
     434            0 :                         enum warn   warn2 = IN_SOME;
     435              : 
     436            0 :                         pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
     437            0 :                         if (warn2 == IN_ALL)
     438            0 :                             warn2 = IN_THIS;
     439            0 :                         if (warn2 > *warnp)
     440            0 :                             *warnp = warn2;
     441              :                     }
     442            0 :                     continue;
     443            0 :                 case 'y':
     444            0 :                     *warnp = IN_ALL;
     445            0 :                     pt = _yconv(t->tm_year, TM_YEAR_BASE,
     446              :                                 false, true,
     447              :                                 pt, ptlim);
     448            0 :                     continue;
     449       904726 :                 case 'Y':
     450       904726 :                     pt = _yconv(t->tm_year, TM_YEAR_BASE,
     451              :                                 true, true,
     452              :                                 pt, ptlim);
     453       904726 :                     continue;
     454       904717 :                 case 'Z':
     455       904717 :                     if (t->tm_zone != NULL)
     456       904717 :                         pt = _add(t->tm_zone, pt, ptlim);
     457              : 
     458              :                     /*
     459              :                      * C99 and later say that %Z must be replaced by the empty
     460              :                      * string if the time zone abbreviation is not
     461              :                      * determinable.
     462              :                      */
     463       904717 :                     continue;
     464            0 :                 case 'z':
     465              :                     {
     466              :                         long        diff;
     467              :                         char const *sign;
     468              :                         bool        negative;
     469              : 
     470            0 :                         if (t->tm_isdst < 0)
     471            0 :                             continue;
     472            0 :                         diff = t->tm_gmtoff;
     473            0 :                         negative = diff < 0;
     474            0 :                         if (diff == 0)
     475              :                         {
     476            0 :                             if (t->tm_zone != NULL)
     477            0 :                                 negative = t->tm_zone[0] == '-';
     478              :                         }
     479            0 :                         if (negative)
     480              :                         {
     481            0 :                             sign = "-";
     482            0 :                             diff = -diff;
     483              :                         }
     484              :                         else
     485            0 :                             sign = "+";
     486            0 :                         pt = _add(sign, pt, ptlim);
     487            0 :                         diff /= SECSPERMIN;
     488            0 :                         diff = (diff / MINSPERHOUR) * 100 +
     489            0 :                             (diff % MINSPERHOUR);
     490            0 :                         pt = _conv(diff, "%04d", pt, ptlim);
     491              :                     }
     492            0 :                     continue;
     493            0 :                 case '+':
     494            0 :                     pt = _fmt(Locale->date_fmt, t, pt, ptlim,
     495              :                               warnp);
     496            0 :                     continue;
     497          800 :                 case '%':
     498              : 
     499              :                     /*
     500              :                      * X311J/88-090 (4.12.3.5): if conversion char is
     501              :                      * undefined, behavior is undefined. Print out the
     502              :                      * character itself as printf(3) also does.
     503              :                      */
     504              :                 default:
     505          800 :                     break;
     506              :             }
     507              :         }
     508      8380720 :         if (pt == ptlim)
     509            0 :             break;
     510      8380720 :         *pt++ = *format;
     511              :     }
     512       904726 :     return pt;
     513              : }
     514              : 
     515              : static char *
     516      6332282 : _conv(int n, const char *format, char *pt, const char *ptlim)
     517              : {
     518              :     char        buf[INT_STRLEN_MAXIMUM(int) + 1];
     519              : 
     520      6332282 :     sprintf(buf, format, n);
     521      6332282 :     return _add(buf, pt, ptlim);
     522              : }
     523              : 
     524              : static char *
     525      7238599 : _add(const char *str, char *pt, const char *ptlim)
     526              : {
     527     22622114 :     while (pt < ptlim && (*pt = *str++) != '\0')
     528     15383515 :         ++pt;
     529      7238599 :     return pt;
     530              : }
     531              : 
     532              : /*
     533              :  * POSIX and the C Standard are unclear or inconsistent about
     534              :  * what %C and %y do if the year is negative or exceeds 9999.
     535              :  * Use the convention that %C concatenated with %y yields the
     536              :  * same output as %Y, and that %Y contains at least 4 bytes,
     537              :  * with more only if necessary.
     538              :  */
     539              : 
     540              : static char *
     541       904726 : _yconv(int a, int b, bool convert_top, bool convert_yy,
     542              :        char *pt, const char *ptlim)
     543              : {
     544              :     int         lead;
     545              :     int         trail;
     546              : 
     547              : #define DIVISOR 100
     548       904726 :     trail = a % DIVISOR + b % DIVISOR;
     549       904726 :     lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
     550       904726 :     trail %= DIVISOR;
     551       904726 :     if (trail < 0 && lead > 0)
     552              :     {
     553            0 :         trail += DIVISOR;
     554            0 :         --lead;
     555              :     }
     556       904726 :     else if (lead < 0 && trail > 0)
     557              :     {
     558            0 :         trail -= DIVISOR;
     559            0 :         ++lead;
     560              :     }
     561       904726 :     if (convert_top)
     562              :     {
     563       904726 :         if (lead == 0 && trail < 0)
     564            0 :             pt = _add("-0", pt, ptlim);
     565              :         else
     566       904726 :             pt = _conv(lead, "%02d", pt, ptlim);
     567              :     }
     568       904726 :     if (convert_yy)
     569       904726 :         pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim);
     570       904726 :     return pt;
     571              : }
        

Generated by: LCOV version 2.0-1