10a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes/* Convert a broken-down time stamp to a string.  */
20a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes
30a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes/* Copyright 1989 The Regents of the University of California.
40a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   All rights reserved.
50a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes
60a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   Redistribution and use in source and binary forms, with or without
70a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   modification, are permitted provided that the following conditions
80a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   are met:
90a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   1. Redistributions of source code must retain the above copyright
100a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes      notice, this list of conditions and the following disclaimer.
110a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   2. Redistributions in binary form must reproduce the above copyright
120a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes      notice, this list of conditions and the following disclaimer in the
130a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes      documentation and/or other materials provided with the distribution.
140a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   3. Neither the name of the University nor the names of its contributors
150a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes      may be used to endorse or promote products derived from this software
160a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes      without specific prior written permission.
170a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes
180a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
190a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
200a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
210a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
220a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
230a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
240a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
250a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
260a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
270a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
280a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes   SUCH DAMAGE.  */
290a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
310a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes** Based on the UCB version with the copyright notice appearing above.
325f564540a953a670925e058dabc521f68ffb997cElliott Hughes**
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** This is ANSIish only when "multibyte character == plain character".
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project*/
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "private.h"
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "tzfile.h"
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "fcntl.h"
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "locale.h"
415f564540a953a670925e058dabc521f68ffb997cElliott Hughes
42a9209d7a0ee7ef40f9a14cab2b6756d7e6f8b919Elliott Hughes#if defined(__BIONIC__)
43905e6d58aaf515bf237e62078f8a321920fe4c6bElliott Hughes
44905e6d58aaf515bf237e62078f8a321920fe4c6bElliott Hughes/* LP32 had a 32-bit time_t, so we need to work around that here. */
4552defb7c702306d4e81c7089cbadd7a6da1d7b6bElliott Hughes#if defined(__LP64__)
4652defb7c702306d4e81c7089cbadd7a6da1d7b6bElliott Hughes#define time64_t time_t
4752defb7c702306d4e81c7089cbadd7a6da1d7b6bElliott Hughes#define mktime64 mktime
4852defb7c702306d4e81c7089cbadd7a6da1d7b6bElliott Hughes#else
49edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#include <time64.h>
5052defb7c702306d4e81c7089cbadd7a6da1d7b6bElliott Hughes#endif
51905e6d58aaf515bf237e62078f8a321920fe4c6bElliott Hughes
525f564540a953a670925e058dabc521f68ffb997cElliott Hughes#include <ctype.h>
53905e6d58aaf515bf237e62078f8a321920fe4c6bElliott Hughes
5439d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes#endif
55905e6d58aaf515bf237e62078f8a321920fe4c6bElliott Hughes
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct lc_time_T {
57edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    mon[MONSPERYEAR];
58edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    month[MONSPERYEAR];
59edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    wday[DAYSPERWEEK];
60edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    weekday[DAYSPERWEEK];
61edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    X_fmt;
62edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    x_fmt;
63edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    c_fmt;
64edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    am;
65edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    pm;
66edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    date_fmt;
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project};
68edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
69edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define Locale  (&C_time_locale)
70edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
71edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Projectstatic const struct lc_time_T   C_time_locale = {
72edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    {
73edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
74edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
75edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }, {
76edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "January", "February", "March", "April", "May", "June",
77edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "July", "August", "September", "October", "November", "December"
78edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }, {
79edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Sun", "Mon", "Tue", "Wed",
80edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Thu", "Fri", "Sat"
81edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }, {
82edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Sunday", "Monday", "Tuesday", "Wednesday",
83edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Thursday", "Friday", "Saturday"
84edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    },
85edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
86edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    /* X_fmt */
87edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    "%H:%M:%S",
88edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
89edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    /*
90edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** x_fmt
91edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** C99 requires this format.
92edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** Using just numbers (as here) makes Quakers happier;
93edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** it's also compatible with SVR4.
94edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    */
95edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    "%m/%d/%y",
96edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
97edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    /*
98edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** c_fmt
99edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** C99 requires this format.
100edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** Previously this code used "%D %X", but we now conform to C99.
101edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** Note that
102edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    **  "%a %b %d %H:%M:%S %Y"
103edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** is used by Solaris 2.3.
104edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    */
105edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    "%a %b %e %T %Y",
106edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
107edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    /* am */
108edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    "AM",
109edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
110edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    /* pm */
111edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    "PM",
112edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
113edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    /* date_fmt */
114edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    "%a %b %e %H:%M:%S %Z %Y"
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project};
1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
117ce4783ce76a4ef888466e02e4c6f3a0a3910bce8Elliott Hughesstatic char *   _add(const char *, char *, const char *, int);
118ce4783ce76a4ef888466e02e4c6f3a0a3910bce8Elliott Hughesstatic char *   _conv(int, const char *, char *, const char *);
119ce4783ce76a4ef888466e02e4c6f3a0a3910bce8Elliott Hughesstatic char *   _fmt(const char *, const struct tm *, char *, const char *,
12039d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes            int *);
1219fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughesstatic char *   _yconv(int, int, bool, bool, char *, const char *, int);
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1230a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes#if !HAVE_POSIX_DECLS
124edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Projectextern char *   tzname[];
1250a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes#endif
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef YEAR_2000_NAME
128edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define YEAR_2000_NAME  "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* !defined YEAR_2000_NAME */
1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
131edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define IN_NONE 0
132edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define IN_SOME 1
133edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define IN_THIS 2
134edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define IN_ALL  3
1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1360a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes#if HAVE_STRFTIME_L
1370a610d00fee344f804d3338c880d73d2de5db143Elliott Hughessize_t
1380a610d00fee344f804d3338c880d73d2de5db143Elliott Hughesstrftime_l(char *s, size_t maxsize, char const *format, struct tm const *t,
1390a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes	   locale_t locale)
1400a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes{
1410a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes  /* Just call strftime, as only the C locale is supported.  */
1420a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes  return strftime(s, maxsize, format, t);
1430a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes}
1440a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes#endif
1450a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes
1460a610d00fee344f804d3338c880d73d2de5db143Elliott Hughes#define FORCE_LOWER_CASE 0x100 /* Android extension. */
1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsize_t
1499fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughesstrftime(char *s, size_t maxsize, const char *format, const struct tm *t)
1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
151edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    char *  p;
152edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    int warn;
153edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
154edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    tzset();
155edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    warn = IN_NONE;
15639d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes    p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
1579a5a3e8e74e2c6d7850ab29711189acf0f7378a2Elliott Hughes#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
158edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
1599fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes        fprintf(stderr, "\n");
160edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        if (format == NULL)
1619fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes            fprintf(stderr, "NULL strftime format ");
1629fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes        else    fprintf(stderr, "strftime format \"%s\" ",
163edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                format);
1649fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes        fprintf(stderr, "yields only two digits of years in ");
165edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        if (warn == IN_SOME)
1669fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes            fprintf(stderr, "some locales");
167edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        else if (warn == IN_THIS)
1689fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes            fprintf(stderr, "the current locale");
1699fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes        else    fprintf(stderr, "all locales");
1709fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes        fprintf(stderr, "\n");
171edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }
1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */
173edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    if (p == s + maxsize)
174edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        return 0;
175edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    *p = '\0';
176edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    return p - s;
1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char *getformat(int modifier, char *normal, char *underscore,
1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                       char *dash, char *zero) {
1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    switch (modifier) {
1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    case '_':
1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return underscore;
1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    case '-':
1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return dash;
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    case '0':
1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return zero;
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return normal;
1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char *
1939fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes_fmt(const char *format, const struct tm *t, char *pt,
1949fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes        const char *ptlim, int *warnp)
1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
196edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    for ( ; *format; ++format) {
197edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        if (*format == '%') {
1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            int modifier = 0;
1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectlabel:
200edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            switch (*++format) {
201edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case '\0':
202edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                --format;
203edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                break;
204edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'A':
205edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _add((t->tm_wday < 0 ||
206edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    t->tm_wday >= DAYSPERWEEK) ?
20739d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                    "?" : Locale->weekday[t->tm_wday],
208edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt, ptlim, modifier);
209edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
210edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'a':
211edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _add((t->tm_wday < 0 ||
212edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    t->tm_wday >= DAYSPERWEEK) ?
21339d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                    "?" : Locale->wday[t->tm_wday],
214edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt, ptlim, modifier);
215edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
216edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'B':
21739d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                pt = _add((t->tm_mon < 0 ||
218a48fa7f4deb6ba703e1da55143771476d4e668ceEric Fischer                                t->tm_mon >= MONSPERYEAR) ?
21939d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                                "?" : Locale->month[t->tm_mon],
220a48fa7f4deb6ba703e1da55143771476d4e668ceEric Fischer                                pt, ptlim, modifier);
221edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
222edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'b':
223edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'h':
224edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _add((t->tm_mon < 0 ||
225edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    t->tm_mon >= MONSPERYEAR) ?
22639d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                    "?" : Locale->mon[t->tm_mon],
227edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt, ptlim, modifier);
228edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
229edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'C':
230edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
231edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** %C used to do a...
232edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                **  _fmt("%a %b %e %X %Y", t);
233edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** ...whereas now POSIX 1003.2 calls for
234edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** something completely different.
235edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** (ado, 1993-05-24)
236edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
2379fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                pt = _yconv(t->tm_year, TM_YEAR_BASE,
2389fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                    true, false, pt, ptlim, modifier);
239edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
240edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'c':
241edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                {
242edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                int warn2 = IN_SOME;
243edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
24439d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
245edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (warn2 == IN_ALL)
246edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    warn2 = IN_THIS;
247edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (warn2 > *warnp)
248edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    *warnp = warn2;
249edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                }
250edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
251edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'D':
25239d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                                pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);
253edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
254edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'd':
2559fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                                pt = _conv(t->tm_mday, getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
256edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
257edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'E':
258edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'O':
259edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
260edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** C99 locale modifiers.
261edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** The sequences
262edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                **  %Ec %EC %Ex %EX %Ey %EY
263edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                **  %Od %oe %OH %OI %Om %OM
264edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                **  %OS %Ou %OU %OV %Ow %OW %Oy
265edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** are supposed to provide alternate
266edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** representations.
267edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
268edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                goto label;
2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            case '_':
2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            case '-':
2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            case '0':
2721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            case '^':
2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            case '#':
2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                modifier = *format;
2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                goto label;
276edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'e':
2779fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                pt = _conv(t->tm_mday, getformat(modifier, "%2d", "%2d", "%d", "%02d"), pt, ptlim);
278edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
279edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'F':
28039d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
281edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
282edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'H':
2839fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                pt = _conv(t->tm_hour, getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
284edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
285edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'I':
286edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv((t->tm_hour % 12) ?
287edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    (t->tm_hour % 12) : 12,
2889fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                    getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
289edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
290edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'j':
2919fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                pt = _conv(t->tm_yday + 1, getformat(modifier, "%03d", "%3d", "%d", "%03d"), pt, ptlim);
292edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
293edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'k':
294edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
295edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** This used to be...
296edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                **  _conv(t->tm_hour % 12 ?
297edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                **      t->tm_hour % 12 : 12, 2, ' ');
298edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** ...and has been changed to the below to
299edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** match SunOS 4.1.1 and Arnold Robbins'
300edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** strftime version 3.0. That is, "%k" and
301edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** "%l" have been swapped.
302edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** (ado, 1993-05-24)
303edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
3049fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                pt = _conv(t->tm_hour, getformat(modifier, "%2d", "%2d", "%d", "%02d"), pt, ptlim);
305edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef KITCHEN_SINK
307edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'K':
308edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
309edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** After all this time, still unclaimed!
310edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
31139d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                pt = _add("kitchen sink", pt, ptlim);
312edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* defined KITCHEN_SINK */
314edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'l':
315edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
316edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** This used to be...
317edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                **  _conv(t->tm_hour, 2, ' ');
318edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** ...and has been changed to the below to
319edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** match SunOS 4.1.1 and Arnold Robbin's
320edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** strftime version 3.0. That is, "%k" and
321edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** "%l" have been swapped.
322edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** (ado, 1993-05-24)
323edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
324edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv((t->tm_hour % 12) ?
325edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    (t->tm_hour % 12) : 12,
3269fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                    getformat(modifier, "%2d", "%2d", "%d", "%02d"), pt, ptlim);
327edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
328edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'M':
3299fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                pt = _conv(t->tm_min, getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
330edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
331edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'm':
3329fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                pt = _conv(t->tm_mon + 1, getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
333edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
334edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'n':
335edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _add("\n", pt, ptlim, modifier);
336edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
337edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'P':
3389fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes            case 'p':
339edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
34039d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                    Locale->pm :
34139d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                    Locale->am,
3429fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                    pt, ptlim, (*format == 'P') ? FORCE_LOWER_CASE : modifier);
343edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
344edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'R':
34539d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                pt = _fmt("%H:%M", t, pt, ptlim, warnp);
346edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
347edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'r':
34839d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp);
349edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
350edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'S':
3519fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                pt = _conv(t->tm_sec, getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
352edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
353edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 's':
354edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                {
355edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    struct tm   tm;
356edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    char        buf[INT_STRLEN_MAXIMUM(
357edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                                time64_t) + 1];
358edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    time64_t    mkt;
359edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
360edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    tm = *t;
361edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    mkt = mktime64(&tm);
362edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    if (TYPE_SIGNED(time64_t))
3639fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                        snprintf(buf, sizeof(buf), "%"PRIdMAX,
3649fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                                 (intmax_t) mkt);
3659fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                    else    snprintf(buf, sizeof(buf), "%"PRIuMAX,
3669fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                                     (uintmax_t) mkt);
367edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt = _add(buf, pt, ptlim, modifier);
368edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                }
369edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
370edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'T':
37139d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp);
372edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
373edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 't':
374edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _add("\t", pt, ptlim, modifier);
375edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
376edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'U':
377edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv((t->tm_yday + DAYSPERWEEK -
378edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    t->tm_wday) / DAYSPERWEEK,
3799fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                    getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
380edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
381edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'u':
382edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
383edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** From Arnold Robbins' strftime version 3.0:
384edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** "ISO 8601: Weekday as a decimal number
385edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** [1 (Monday) - 7]"
386edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** (ado, 1993-05-24)
387edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
388edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv((t->tm_wday == 0) ?
3899fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                    DAYSPERWEEK : t->tm_wday,
3909fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                    "%d", pt, ptlim);
391edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
392edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'V':   /* ISO 8601 week number */
393edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'G':   /* ISO 8601 year (four digits) */
394edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'g':   /* ISO 8601 year (two digits) */
3951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
3961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** From Arnold Robbins' strftime version 3.0: "the week number of the
3971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** year (the first Monday as the first day of week 1) as a decimal number
3981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** (01-53)."
3991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** (ado, 1993-05-24)
4001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project**
40139d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes** From <http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html> by Markus Kuhn:
4021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** "Week 01 of a year is per definition the first week which has the
4031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** Thursday in this year, which is equivalent to the week which contains
4041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** the fourth day of January. In other words, the first week of a new year
4051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** is the week which has the majority of its days in the new year. Week 01
4061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** might also contain days from the previous year and the week before week
4071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** 01 of a year is the last week (52 or 53) of the previous year even if
4081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** it contains days from the new year. A week starts with Monday (day 1)
4091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** and ends with Sunday (day 7). For example, the first week of the year
4101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** 1997 lasts from 1996-12-30 to 1997-01-05..."
4111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** (ado, 1996-01-02)
4121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project*/
413edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                {
414edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    int year;
415edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    int base;
416edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    int yday;
417edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    int wday;
418edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    int w;
419edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
420edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    year = t->tm_year;
421edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    base = TM_YEAR_BASE;
422edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    yday = t->tm_yday;
423edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    wday = t->tm_wday;
424edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    for ( ; ; ) {
425edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        int len;
426edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        int bot;
427edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        int top;
428edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
429edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        len = isleap_sum(year, base) ?
430edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            DAYSPERLYEAR :
431edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            DAYSPERNYEAR;
432edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        /*
433edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        ** What yday (-3 ... 3) does
434edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        ** the ISO year begin on?
435edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        */
436edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        bot = ((yday + 11 - wday) %
437edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            DAYSPERWEEK) - 3;
438edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        /*
439edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        ** What yday does the NEXT
440edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        ** ISO year begin on?
441edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        */
442edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        top = bot -
443edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            (len % DAYSPERWEEK);
444edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        if (top < -3)
445edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            top += DAYSPERWEEK;
446edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        top += len;
447edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        if (yday >= top) {
448edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            ++base;
449edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            w = 1;
450edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            break;
451edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        }
452edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        if (yday >= bot) {
453edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            w = 1 + ((yday - bot) /
454edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                                DAYSPERWEEK);
455edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            break;
456edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        }
457edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        --base;
458edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        yday += isleap_sum(year, base) ?
459edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            DAYSPERLYEAR :
460edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            DAYSPERNYEAR;
461edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    }
4621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef XPG4_1994_04_09
463edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    if ((w == 52 &&
464edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        t->tm_mon == TM_JANUARY) ||
465edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        (w == 1 &&
466edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        t->tm_mon == TM_DECEMBER))
467edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            w = 53;
4681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* defined XPG4_1994_04_09 */
469edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    if (*format == 'V')
4709fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                        pt = _conv(w, getformat(modifier, "%02d", "%2d", "%d", "%02d"),
471edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                               pt, ptlim);
472edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    else if (*format == 'g') {
473edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        *warnp = IN_ALL;
4749fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                        pt = _yconv(year, base,
4759fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                            false, true,
476edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            pt, ptlim, modifier);
4779fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                    } else  pt = _yconv(year, base,
4789fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                            true, true,
479edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            pt, ptlim, modifier);
480edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                }
481edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
482edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'v':
483edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
484edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** From Arnold Robbins' strftime version 3.0:
485edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** "date as dd-bbb-YYYY"
486edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** (ado, 1993-05-24)
487edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
48839d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp);
489edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
490edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'W':
491edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv((t->tm_yday + DAYSPERWEEK -
492edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    (t->tm_wday ?
493edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    (t->tm_wday - 1) :
494edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    (DAYSPERWEEK - 1))) / DAYSPERWEEK,
4959fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                    getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
496edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
497edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'w':
498edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv(t->tm_wday, "%d", pt, ptlim);
499edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
500edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'X':
50139d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp);
502edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
503edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'x':
504edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                {
505edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                int warn2 = IN_SOME;
506edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
50739d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
508edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (warn2 == IN_ALL)
509edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    warn2 = IN_THIS;
510edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (warn2 > *warnp)
511edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    *warnp = warn2;
512edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                }
513edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
514edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'y':
515edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                *warnp = IN_ALL;
5169fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                pt = _yconv(t->tm_year, TM_YEAR_BASE,
5179fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                    false, true,
518edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt, ptlim, modifier);
519edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
520edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'Y':
5219fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                pt = _yconv(t->tm_year, TM_YEAR_BASE,
5229fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                    true, true,
523edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt, ptlim, modifier);
524edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
525edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'Z':
5261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef TM_ZONE
527a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes                // BEGIN: Android-changed.
528a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes                {
529a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes                    const char* zone = t->TM_ZONE;
530a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes                    if (!zone || !*zone) {
531a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes                        // "The value of tm_isdst shall be positive if Daylight Savings Time is
532a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes                        // in effect, 0 if Daylight Savings Time is not in effect, and negative
533a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes                        // if the information is not available."
534a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes                        if (t->tm_isdst == 0) zone = tzname[0];
535a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes                        else if (t->tm_isdst > 0) zone = tzname[1];
536a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes
537a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes                        // "Replaced by the timezone name or abbreviation, or by no bytes if no
538a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes                        // timezone information exists."
539a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes                        if (!zone || !*zone) zone = "";
540a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes                    }
541a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes                    pt = _add(zone, pt, ptlim, modifier);
542a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes                }
543a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7Elliott Hughes                // END: Android-changed.
5449fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes#else
545edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (t->tm_isdst >= 0)
546edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt = _add(tzname[t->tm_isdst != 0],
5479fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                        pt, ptlim);
5489fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes#endif
549edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
550edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** C99 says that %Z must be replaced by the
551edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** empty string if the time zone is not
552edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** determinable.
553edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
554edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
555edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'z':
556edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                {
557e0d0b15de6eaee6c3975e13ad2b0e1238d0fdd8fElliott Hughes                long     diff;
558edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                char const *    sign;
559edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
560edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (t->tm_isdst < 0)
561edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    continue;
5621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef TM_GMTOFF
563edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                diff = t->TM_GMTOFF;
5641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else /* !defined TM_GMTOFF */
565edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
566e0d0b15de6eaee6c3975e13ad2b0e1238d0fdd8fElliott Hughes                ** C99 says that the UT offset must
567edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** be computed by looking only at
568edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** tm_isdst. This requirement is
569edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** incorrect, since it means the code
570edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** must rely on magic (in this case
571edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** altzone and timezone), and the
572edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** magic might not have the correct
573edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** offset. Doing things correctly is
574edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** tricky and requires disobeying C99;
575edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** see GNU C strftime for details.
576edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** For now, punt and conform to the
577edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** standard, even though it's incorrect.
578edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                **
579edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** C99 says that %z must be replaced by the
580edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** empty string if the time zone is not
581edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** determinable, so output nothing if the
582edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** appropriate variables are not available.
583edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
584edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (t->tm_isdst == 0)
5851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef USG_COMPAT
586edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    diff = -timezone;
5871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else /* !defined USG_COMPAT */
588edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    continue;
5891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* !defined USG_COMPAT */
590edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                else
5911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef ALTZONE
592edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    diff = -altzone;
5931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else /* !defined ALTZONE */
594edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    continue;
5951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* !defined ALTZONE */
5961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* !defined TM_GMTOFF */
597edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (diff < 0) {
598edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    sign = "-";
599edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    diff = -diff;
600edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                } else  sign = "+";
601edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _add(sign, pt, ptlim, modifier);
602edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                diff /= SECSPERMIN;
603edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                diff = (diff / MINSPERHOUR) * 100 +
604edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    (diff % MINSPERHOUR);
6059fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes                pt = _conv(diff, getformat(modifier, "%04d", "%4d", "%d", "%04d"), pt, ptlim);
606edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                }
607edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
608edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case '+':
60939d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                pt = _fmt(Locale->date_fmt, t, pt, ptlim,
61039d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes                    warnp);
611edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
612edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case '%':
613edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            /*
614edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            ** X311J/88-090 (4.12.3.5): if conversion char is
615edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            ** undefined, behavior is undefined. Print out the
616edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            ** character itself as printf(3) also does.
617edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            */
618edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            default:
619edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                break;
620edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            }
621edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        }
622edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        if (pt == ptlim)
623edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
624edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        *pt++ = *format;
625edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }
626edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    return pt;
6271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char *
6309fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes_conv(int n, const char *format, char *pt, const char *ptlim)
6311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
6329fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes	char	buf[INT_STRLEN_MAXIMUM(int) + 1];
6331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6349fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes	snprintf(buf, sizeof(buf), format, n);
6359fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes	return _add(buf, pt, ptlim, 0);
6361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char *
63939d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes_add(const char *str, char *pt, const char *const ptlim, int modifier)
6401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
6411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        int c;
6421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        switch (modifier) {
6441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        case FORCE_LOWER_CASE:
6451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                while (pt < ptlim && (*pt = tolower(*str++)) != '\0') {
6461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        ++pt;
6471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                }
6481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                break;
6491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        case '^':
6511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                while (pt < ptlim && (*pt = toupper(*str++)) != '\0') {
6521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        ++pt;
6531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                }
6541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                break;
6551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        case '#':
6571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                while (pt < ptlim && (c = *str++) != '\0') {
6581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        if (isupper(c)) {
6591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                c = tolower(c);
6601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        } else if (islower(c)) {
6611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                c = toupper(c);
6621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        }
6631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        *pt = c;
6641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        ++pt;
6651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                }
6661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                break;
6681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        default:
6701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                while (pt < ptlim && (*pt = *str++) != '\0') {
6711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        ++pt;
6721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                }
6731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        }
6741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
675edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    return pt;
6761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
6791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** POSIX and the C Standard are unclear or inconsistent about
6801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** what %C and %y do if the year is negative or exceeds 9999.
6811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** Use the convention that %C concatenated with %y yields the
6821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** same output as %Y, and that %Y contains at least 4 bytes,
6831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** with more only if necessary.
6841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project*/
6851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char *
6879fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes_yconv(int a, int b, bool convert_top, bool convert_yy,
6889fb22a3ec4ec5217fc29bb3ee3a0f1076098151fElliott Hughes       char *pt, const char *ptlim, int modifier)
6891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
690edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    register int    lead;
691edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    register int    trail;
692edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
693edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define DIVISOR 100
694edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    trail = a % DIVISOR + b % DIVISOR;
695edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
696edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    trail %= DIVISOR;
697edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    if (trail < 0 && lead > 0) {
698edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        trail += DIVISOR;
699edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        --lead;
700edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    } else if (lead < 0 && trail > 0) {
701edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        trail -= DIVISOR;
702edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        ++lead;
703edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }
704edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    if (convert_top) {
705edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        if (lead == 0 && trail < 0)
706edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            pt = _add("-0", pt, ptlim, modifier);
70739d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes        else    pt = _conv(lead, getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
708edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }
709edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    if (convert_yy)
71039d903aea901cd29a4eef3a82c2dbda59b5bc292Elliott Hughes        pt = _conv(((trail < 0) ? -trail : trail), getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
711edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    return pt;
7121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
713