11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
25f564540a953a670925e058dabc521f68ffb997cElliott Hughes** Based on the UCB version with the copyright notice and sccsid
35f564540a953a670925e058dabc521f68ffb997cElliott Hughes** appearing below.
45f564540a953a670925e058dabc521f68ffb997cElliott Hughes**
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** This is ANSIish only when "multibyte character == plain character".
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project*/
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "private.h"
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** Copyright (c) 1989 The Regents of the University of California.
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** All rights reserved.
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project**
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** Redistribution and use in source and binary forms are permitted
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** provided that the above copyright notice and this paragraph are
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** duplicated in all such forms and that any documentation,
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** advertising materials, and other materials related to such
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** distribution and use acknowledge that the software was developed
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** by the University of California, Berkeley. The name of the
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** University may not be used to endorse or promote products derived
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** from this software without specific prior written permission.
225f564540a953a670925e058dabc521f68ffb997cElliott Hughes** THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project*/
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "tzfile.h"
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "fcntl.h"
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "locale.h"
305f564540a953a670925e058dabc521f68ffb997cElliott Hughes
315f564540a953a670925e058dabc521f68ffb997cElliott Hughes#if __ANDROID__
32708c11205443cda14cfb21138d441106aa77a5f9Elliott Hughes
33708c11205443cda14cfb21138d441106aa77a5f9Elliott Hughes/* LP32 had a 32-bit time_t, so we need to work around that here. */
3452defb7c702306d4e81c7089cbadd7a6da1d7b6bElliott Hughes#if defined(__LP64__)
3552defb7c702306d4e81c7089cbadd7a6da1d7b6bElliott Hughes#define time64_t time_t
3652defb7c702306d4e81c7089cbadd7a6da1d7b6bElliott Hughes#define mktime64 mktime
3752defb7c702306d4e81c7089cbadd7a6da1d7b6bElliott Hughes#else
38edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#include <time64.h>
3952defb7c702306d4e81c7089cbadd7a6da1d7b6bElliott Hughes#endif
40708c11205443cda14cfb21138d441106aa77a5f9Elliott Hughes
415f564540a953a670925e058dabc521f68ffb997cElliott Hughes#include <ctype.h>
42708c11205443cda14cfb21138d441106aa77a5f9Elliott Hughes
43c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes#endif
44708c11205443cda14cfb21138d441106aa77a5f9Elliott Hughes
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct lc_time_T {
46edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    mon[MONSPERYEAR];
47edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    month[MONSPERYEAR];
48edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    wday[DAYSPERWEEK];
49edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    weekday[DAYSPERWEEK];
50edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    X_fmt;
51edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    x_fmt;
52edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    c_fmt;
53edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    am;
54edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    pm;
55edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *    date_fmt;
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project};
57edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
58c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes#ifdef LOCALE_HOME
595f564540a953a670925e058dabc521f68ffb997cElliott Hughes#include "sys/stat.h"
605f564540a953a670925e058dabc521f68ffb997cElliott Hughesstatic struct lc_time_T                localebuf;
615f564540a953a670925e058dabc521f68ffb997cElliott Hughesstatic struct lc_time_T *      _loc(void);
625f564540a953a670925e058dabc521f68ffb997cElliott Hughes#define Locale _loc()
635f564540a953a670925e058dabc521f68ffb997cElliott Hughes#endif /* defined LOCALE_HOME */
645f564540a953a670925e058dabc521f68ffb997cElliott Hughes#ifndef LOCALE_HOME
65edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define Locale  (&C_time_locale)
665f564540a953a670925e058dabc521f68ffb997cElliott Hughes#endif /* !defined LOCALE_HOME */
67edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
68edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Projectstatic const struct lc_time_T   C_time_locale = {
69edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    {
70edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
71edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
72edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }, {
73edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "January", "February", "March", "April", "May", "June",
74edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "July", "August", "September", "October", "November", "December"
75edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }, {
76edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Sun", "Mon", "Tue", "Wed",
77edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Thu", "Fri", "Sat"
78edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }, {
79edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Sunday", "Monday", "Tuesday", "Wednesday",
80edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Thursday", "Friday", "Saturday"
81edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    },
82edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
83edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    /* X_fmt */
84edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    "%H:%M:%S",
85edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
86edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    /*
87edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** x_fmt
88edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** C99 requires this format.
89edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** Using just numbers (as here) makes Quakers happier;
90edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** it's also compatible with SVR4.
91edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    */
92edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    "%m/%d/%y",
93edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
94edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    /*
95edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** c_fmt
96edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** C99 requires this format.
97edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** Previously this code used "%D %X", but we now conform to C99.
98edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** Note that
99edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    **  "%a %b %d %H:%M:%S %Y"
100edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    ** is used by Solaris 2.3.
101edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    */
102edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    "%a %b %e %T %Y",
103edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
104edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    /* am */
105edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    "AM",
106edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
107edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    /* pm */
108edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    "PM",
109edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
110edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    /* date_fmt */
111edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    "%a %b %e %H:%M:%S %Z %Y"
1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project};
1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
114ce4783ce76a4ef888466e02e4c6f3a0a3910bce8Elliott Hughesstatic char *   _add(const char *, char *, const char *, int);
115ce4783ce76a4ef888466e02e4c6f3a0a3910bce8Elliott Hughesstatic char *   _conv(int, const char *, char *, const char *);
116ce4783ce76a4ef888466e02e4c6f3a0a3910bce8Elliott Hughesstatic char *   _fmt(const char *, const struct tm *, char *, const char *,
117c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes            int *);
118ce4783ce76a4ef888466e02e4c6f3a0a3910bce8Elliott Hughesstatic char *   _yconv(int, int, int, int, char *, const char *, int);
119ce4783ce76a4ef888466e02e4c6f3a0a3910bce8Elliott Hughesstatic char *   getformat(int, char *, char *, char *, char *);
1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
121edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Projectextern char *   tzname[];
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef YEAR_2000_NAME
124edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define YEAR_2000_NAME  "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* !defined YEAR_2000_NAME */
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
127edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define IN_NONE 0
128edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define IN_SOME 1
129edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define IN_THIS 2
130edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define IN_ALL  3
1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define FORCE_LOWER_CASE 0x100
1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsize_t
135c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughesstrftime(char * const s, const size_t maxsize, const char *const format,
136c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes        const struct tm *const t)
1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
138edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    char *  p;
139edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    int warn;
140edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
141edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    tzset();
142c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes#ifdef LOCALE_HOME
143c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes    localebuf.mon[0] = 0;
144c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes#endif /* defined LOCALE_HOME */
145edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    warn = IN_NONE;
146c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes    p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
1479a5a3e8e74e2c6d7850ab29711189acf0f7378a2Elliott Hughes#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
148edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
149edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        (void) fprintf(stderr, "\n");
150edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        if (format == NULL)
151edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            (void) fprintf(stderr, "NULL strftime format ");
152edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        else    (void) fprintf(stderr, "strftime format \"%s\" ",
153edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                format);
154edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        (void) fprintf(stderr, "yields only two digits of years in ");
155edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        if (warn == IN_SOME)
156edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            (void) fprintf(stderr, "some locales");
157edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        else if (warn == IN_THIS)
158edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            (void) fprintf(stderr, "the current locale");
159edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        else    (void) fprintf(stderr, "all locales");
160edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        (void) fprintf(stderr, "\n");
161edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }
1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */
163edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    if (p == s + maxsize)
164edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        return 0;
165edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    *p = '\0';
166edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    return p - s;
1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char *getformat(int modifier, char *normal, char *underscore,
1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                       char *dash, char *zero) {
1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    switch (modifier) {
1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    case '_':
1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return underscore;
1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    case '-':
1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return dash;
1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    case '0':
1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return zero;
1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return normal;
1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char *
186c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes_fmt(const char *format, const struct tm *const t, char * pt,
187c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes        const char *const ptlim, int *warnp)
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
189edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    for ( ; *format; ++format) {
190edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        if (*format == '%') {
1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            int modifier = 0;
1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectlabel:
193edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            switch (*++format) {
194edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case '\0':
195edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                --format;
196edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                break;
197edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'A':
198edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _add((t->tm_wday < 0 ||
199edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    t->tm_wday >= DAYSPERWEEK) ?
200c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                    "?" : Locale->weekday[t->tm_wday],
201edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt, ptlim, modifier);
202edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
203edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'a':
204edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _add((t->tm_wday < 0 ||
205edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    t->tm_wday >= DAYSPERWEEK) ?
206c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                    "?" : Locale->wday[t->tm_wday],
207edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt, ptlim, modifier);
208edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
209edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'B':
210c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                pt = _add((t->tm_mon < 0 ||
211a48fa7f4deb6ba703e1da55143771476d4e668ceEric Fischer                                t->tm_mon >= MONSPERYEAR) ?
212c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                                "?" : Locale->month[t->tm_mon],
213a48fa7f4deb6ba703e1da55143771476d4e668ceEric Fischer                                pt, ptlim, modifier);
214edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
215edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'b':
216edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'h':
217edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _add((t->tm_mon < 0 ||
218edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    t->tm_mon >= MONSPERYEAR) ?
219c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                    "?" : Locale->mon[t->tm_mon],
220edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt, ptlim, modifier);
221edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
222edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'C':
223edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
224edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** %C used to do a...
225edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                **  _fmt("%a %b %e %X %Y", t);
226edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** ...whereas now POSIX 1003.2 calls for
227edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** something completely different.
228edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** (ado, 1993-05-24)
229edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
230edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,
231edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt, ptlim, modifier);
232edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
233edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'c':
234edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                {
235edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                int warn2 = IN_SOME;
236edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
237c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
238edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (warn2 == IN_ALL)
239edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    warn2 = IN_THIS;
240edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (warn2 > *warnp)
241edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    *warnp = warn2;
242edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                }
243edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
244edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'D':
245c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                                pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);
246edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
247edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'd':
2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                pt = _conv(t->tm_mday,
2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                           getformat(modifier, "%02d",
2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                                     "%2d", "%d", "%02d"),
2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                           pt, ptlim);
252edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
253edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'E':
254edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'O':
255edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
256edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** C99 locale modifiers.
257edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** The sequences
258edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                **  %Ec %EC %Ex %EX %Ey %EY
259edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                **  %Od %oe %OH %OI %Om %OM
260edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                **  %OS %Ou %OU %OV %Ow %OW %Oy
261edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** are supposed to provide alternate
262edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** representations.
263edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
264edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                goto label;
2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            case '_':
2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            case '-':
2671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            case '0':
2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            case '^':
2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            case '#':
2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                modifier = *format;
2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                goto label;
272edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'e':
273edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv(t->tm_mday,
2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                           getformat(modifier, "%2d",
2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                                     "%2d", "%d", "%02d"),
2761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                           pt, ptlim);
277edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
278edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'F':
279c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
280edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
281edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'H':
282edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv(t->tm_hour,
2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                           getformat(modifier, "%02d",
2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                                     "%2d", "%d", "%02d"),
2851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                           pt, ptlim);
286edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
287edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'I':
288edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv((t->tm_hour % 12) ?
289edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    (t->tm_hour % 12) : 12,
290edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    getformat(modifier, "%02d",
2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                                  "%2d", "%d", "%02d"),
2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                        pt, ptlim);
293edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
294edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'j':
295edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv(t->tm_yday + 1,
2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                           getformat(modifier, "%03d", "%3d", "%d", "%03d"),
2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                           pt, ptlim);
298edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
299edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'k':
300edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
301edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** This used to be...
302edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                **  _conv(t->tm_hour % 12 ?
303edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                **      t->tm_hour % 12 : 12, 2, ' ');
304edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** ...and has been changed to the below to
305edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** match SunOS 4.1.1 and Arnold Robbins'
306edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** strftime version 3.0. That is, "%k" and
307edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** "%l" have been swapped.
308edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** (ado, 1993-05-24)
309edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
310edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv(t->tm_hour,
3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                           getformat(modifier, "%2d",
3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                                     "%2d", "%d", "%02d"),
3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                           pt, ptlim);
314edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef KITCHEN_SINK
316edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'K':
317edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
318edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** After all this time, still unclaimed!
319edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
320c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                pt = _add("kitchen sink", pt, ptlim);
321edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* defined KITCHEN_SINK */
323edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'l':
324edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
325edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** This used to be...
326edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                **  _conv(t->tm_hour, 2, ' ');
327edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** ...and has been changed to the below to
328edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** match SunOS 4.1.1 and Arnold Robbin's
329edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** strftime version 3.0. That is, "%k" and
330edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** "%l" have been swapped.
331edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** (ado, 1993-05-24)
332edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
333edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv((t->tm_hour % 12) ?
334edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    (t->tm_hour % 12) : 12,
335edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    getformat(modifier, "%2d",
3361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                                  "%2d", "%d", "%02d"),
3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                        pt, ptlim);
338edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
339edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'M':
340edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv(t->tm_min,
3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                           getformat(modifier, "%02d",
3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                                     "%2d", "%d", "%02d"),
3431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                           pt, ptlim);
344edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
345edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'm':
346edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv(t->tm_mon + 1,
3471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                           getformat(modifier, "%02d",
3481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                                     "%2d", "%d", "%02d"),
3491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                           pt, ptlim);
350edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
351edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'n':
352edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _add("\n", pt, ptlim, modifier);
353edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
354edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'p':
355edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
356c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                    Locale->pm :
357c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                    Locale->am,
358edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt, ptlim, modifier);
359edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
360edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'P':
361edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
362c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                    Locale->pm :
363c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                    Locale->am,
364edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt, ptlim, FORCE_LOWER_CASE);
365edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
366edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'R':
367c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                pt = _fmt("%H:%M", t, pt, ptlim, warnp);
368edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
369edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'r':
370c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp);
371edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
372edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'S':
373edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv(t->tm_sec,
3741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                           getformat(modifier, "%02d",
3751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                                     "%2d", "%d", "%02d"),
3761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                           pt, ptlim);
377edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
378edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 's':
379edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                {
380edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    struct tm   tm;
381edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    char        buf[INT_STRLEN_MAXIMUM(
382edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                                time64_t) + 1];
383edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    time64_t    mkt;
384edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
385edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    tm = *t;
386edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    mkt = mktime64(&tm);
387edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    if (TYPE_SIGNED(time64_t))
388e6cff939e603e445c2576958c3777d7b7f5d84faJim Huang                        (void) snprintf(buf, sizeof(buf), "%lld",
389edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            (long long) mkt);
390e6cff939e603e445c2576958c3777d7b7f5d84faJim Huang                    else    (void) snprintf(buf, sizeof(buf), "%llu",
391edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            (unsigned long long) mkt);
392edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt = _add(buf, pt, ptlim, modifier);
393edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                }
394edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
395edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'T':
396c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp);
397edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
398edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 't':
399edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _add("\t", pt, ptlim, modifier);
400edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
401edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'U':
402edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv((t->tm_yday + DAYSPERWEEK -
403edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    t->tm_wday) / DAYSPERWEEK,
404edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    getformat(modifier, "%02d",
4051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                                  "%2d", "%d", "%02d"),
4061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                        pt, ptlim);
407edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
408edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'u':
409edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
410edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** From Arnold Robbins' strftime version 3.0:
411edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** "ISO 8601: Weekday as a decimal number
412edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** [1 (Monday) - 7]"
413edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** (ado, 1993-05-24)
414edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
415edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv((t->tm_wday == 0) ?
416edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    DAYSPERWEEK : t->tm_wday, "%d", pt, ptlim);
417edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
418edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'V':   /* ISO 8601 week number */
419edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'G':   /* ISO 8601 year (four digits) */
420edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'g':   /* ISO 8601 year (two digits) */
4211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
4221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** From Arnold Robbins' strftime version 3.0: "the week number of the
4231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** year (the first Monday as the first day of week 1) as a decimal number
4241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** (01-53)."
4251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** (ado, 1993-05-24)
4261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project**
427c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes** From <http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html> by Markus Kuhn:
4281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** "Week 01 of a year is per definition the first week which has the
4291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** Thursday in this year, which is equivalent to the week which contains
4301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** the fourth day of January. In other words, the first week of a new year
4311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** is the week which has the majority of its days in the new year. Week 01
4321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** might also contain days from the previous year and the week before week
4331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** 01 of a year is the last week (52 or 53) of the previous year even if
4341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** it contains days from the new year. A week starts with Monday (day 1)
4351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** and ends with Sunday (day 7). For example, the first week of the year
4361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** 1997 lasts from 1996-12-30 to 1997-01-05..."
4371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** (ado, 1996-01-02)
4381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project*/
439edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                {
440edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    int year;
441edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    int base;
442edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    int yday;
443edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    int wday;
444edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    int w;
445edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
446edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    year = t->tm_year;
447edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    base = TM_YEAR_BASE;
448edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    yday = t->tm_yday;
449edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    wday = t->tm_wday;
450edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    for ( ; ; ) {
451edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        int len;
452edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        int bot;
453edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        int top;
454edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
455edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        len = isleap_sum(year, base) ?
456edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            DAYSPERLYEAR :
457edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            DAYSPERNYEAR;
458edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        /*
459edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        ** What yday (-3 ... 3) does
460edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        ** the ISO year begin on?
461edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        */
462edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        bot = ((yday + 11 - wday) %
463edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            DAYSPERWEEK) - 3;
464edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        /*
465edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        ** What yday does the NEXT
466edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        ** ISO year begin on?
467edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        */
468edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        top = bot -
469edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            (len % DAYSPERWEEK);
470edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        if (top < -3)
471edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            top += DAYSPERWEEK;
472edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        top += len;
473edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        if (yday >= top) {
474edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            ++base;
475edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            w = 1;
476edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            break;
477edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        }
478edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        if (yday >= bot) {
479edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            w = 1 + ((yday - bot) /
480edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                                DAYSPERWEEK);
481edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            break;
482edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        }
483edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        --base;
484edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        yday += isleap_sum(year, base) ?
485edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            DAYSPERLYEAR :
486edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            DAYSPERNYEAR;
487edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    }
4881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef XPG4_1994_04_09
489edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    if ((w == 52 &&
490edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        t->tm_mon == TM_JANUARY) ||
491edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        (w == 1 &&
492edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        t->tm_mon == TM_DECEMBER))
493edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            w = 53;
4941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* defined XPG4_1994_04_09 */
495edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    if (*format == 'V')
496edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        pt = _conv(w,
497c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                                getformat(modifier, "%02d", "%2d", "%d", "%02d"),
498edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                               pt, ptlim);
499edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    else if (*format == 'g') {
500edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        *warnp = IN_ALL;
501edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        pt = _yconv(year, base, 0, 1,
502edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            pt, ptlim, modifier);
503edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    } else  pt = _yconv(year, base, 1, 1,
504edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                            pt, ptlim, modifier);
505edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                }
506edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
507edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'v':
508edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
509edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** From Arnold Robbins' strftime version 3.0:
510edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** "date as dd-bbb-YYYY"
511edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** (ado, 1993-05-24)
512edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
513c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp);
514edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
515edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'W':
516edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv((t->tm_yday + DAYSPERWEEK -
517edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    (t->tm_wday ?
518edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    (t->tm_wday - 1) :
519edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    (DAYSPERWEEK - 1))) / DAYSPERWEEK,
520edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    getformat(modifier, "%02d",
5211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                                  "%2d", "%d", "%02d"),
5221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                        pt, ptlim);
523edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
524edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'w':
525edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv(t->tm_wday, "%d", pt, ptlim);
526edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
527edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'X':
528c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp);
529edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
530edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'x':
531edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                {
532edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                int warn2 = IN_SOME;
533edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
534c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
535edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (warn2 == IN_ALL)
536edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    warn2 = IN_THIS;
537edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (warn2 > *warnp)
538edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    *warnp = warn2;
539edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                }
540edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
541edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'y':
542edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                *warnp = IN_ALL;
543edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1,
544edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt, ptlim, modifier);
545edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
546edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'Y':
547edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1,
548edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt, ptlim, modifier);
549edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
550edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'Z':
5511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef TM_ZONE
552edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (t->TM_ZONE != NULL)
553edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt = _add(t->TM_ZONE, pt, ptlim,
5541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                                  modifier);
555edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                else
5561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* defined TM_ZONE */
557edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (t->tm_isdst >= 0)
558edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    pt = _add(tzname[t->tm_isdst != 0],
559edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                        pt, ptlim, modifier);
560edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
561edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** C99 says that %Z must be replaced by the
562edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** empty string if the time zone is not
563edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** determinable.
564edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
565edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
566edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case 'z':
567edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                {
568e0d0b15de6eaee6c3975e13ad2b0e1238d0fdd8fElliott Hughes                long     diff;
569edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                char const *    sign;
570edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
571edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (t->tm_isdst < 0)
572edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    continue;
5731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef TM_GMTOFF
574edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                diff = t->TM_GMTOFF;
5751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else /* !defined TM_GMTOFF */
576edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /*
577e0d0b15de6eaee6c3975e13ad2b0e1238d0fdd8fElliott Hughes                ** C99 says that the UT offset must
578edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** be computed by looking only at
579edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** tm_isdst. This requirement is
580edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** incorrect, since it means the code
581edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** must rely on magic (in this case
582edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** altzone and timezone), and the
583edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** magic might not have the correct
584edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** offset. Doing things correctly is
585edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** tricky and requires disobeying C99;
586edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** see GNU C strftime for details.
587edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** For now, punt and conform to the
588edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** standard, even though it's incorrect.
589edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                **
590edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** C99 says that %z must be replaced by the
591edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** empty string if the time zone is not
592edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** determinable, so output nothing if the
593edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                ** appropriate variables are not available.
594edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                */
595edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (t->tm_isdst == 0)
5961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef USG_COMPAT
597edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    diff = -timezone;
5981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else /* !defined USG_COMPAT */
599edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    continue;
6001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* !defined USG_COMPAT */
601edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                else
6021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef ALTZONE
603edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    diff = -altzone;
6041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else /* !defined ALTZONE */
605edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    continue;
6061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* !defined ALTZONE */
6071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* !defined TM_GMTOFF */
608edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (diff < 0) {
609edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    sign = "-";
610edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    diff = -diff;
611edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                } else  sign = "+";
612edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _add(sign, pt, ptlim, modifier);
613edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                diff /= SECSPERMIN;
614edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                diff = (diff / MINSPERHOUR) * 100 +
615edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    (diff % MINSPERHOUR);
616edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                pt = _conv(diff,
6171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                           getformat(modifier, "%04d",
6181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                                     "%4d", "%d", "%04d"),
6191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                           pt, ptlim);
620edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                }
621edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
622edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case '+':
623c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                pt = _fmt(Locale->date_fmt, t, pt, ptlim,
624c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes                    warnp);
625edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                continue;
626edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            case '%':
627edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            /*
628edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            ** X311J/88-090 (4.12.3.5): if conversion char is
629edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            ** undefined, behavior is undefined. Print out the
630edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            ** character itself as printf(3) also does.
631edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            */
632edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            default:
633edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                break;
634edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            }
635edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        }
636edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        if (pt == ptlim)
637edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
638edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        *pt++ = *format;
639edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }
640edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    return pt;
6411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char *
644c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes_conv(const int n, const char *const format, char *const pt,
645c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes        const char *const ptlim)
6461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
647edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    char    buf[INT_STRLEN_MAXIMUM(int) + 1];
6481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
649edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    (void) snprintf(buf, sizeof(buf), format, n);
650edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    return _add(buf, pt, ptlim, 0);
6511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char *
654c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes_add(const char *str, char *pt, const char *const ptlim, int modifier)
6551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
6561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        int c;
6571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        switch (modifier) {
6591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        case FORCE_LOWER_CASE:
6601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                while (pt < ptlim && (*pt = tolower(*str++)) != '\0') {
6611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        ++pt;
6621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                }
6631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                break;
6641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        case '^':
6661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                while (pt < ptlim && (*pt = toupper(*str++)) != '\0') {
6671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        ++pt;
6681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                }
6691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                break;
6701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        case '#':
6721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                while (pt < ptlim && (c = *str++) != '\0') {
6731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        if (isupper(c)) {
6741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                c = tolower(c);
6751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        } else if (islower(c)) {
6761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                c = toupper(c);
6771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        }
6781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        *pt = c;
6791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        ++pt;
6801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                }
6811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                break;
6831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        default:
6851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                while (pt < ptlim && (*pt = *str++) != '\0') {
6861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        ++pt;
6871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                }
6881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        }
6891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
690edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    return pt;
6911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
6941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** POSIX and the C Standard are unclear or inconsistent about
6951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** what %C and %y do if the year is negative or exceeds 9999.
6961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** Use the convention that %C concatenated with %y yields the
6971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** same output as %Y, and that %Y contains at least 4 bytes,
6981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project** with more only if necessary.
6991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project*/
7001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char *
702c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes_yconv(const int a, const int b, const int convert_top, const int convert_yy,
703c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes        char *pt, const char *const ptlim, int modifier)
7041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
705edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    register int    lead;
706edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    register int    trail;
707edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
708edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define DIVISOR 100
709edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    trail = a % DIVISOR + b % DIVISOR;
710edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
711edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    trail %= DIVISOR;
712edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    if (trail < 0 && lead > 0) {
713edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        trail += DIVISOR;
714edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        --lead;
715edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    } else if (lead < 0 && trail > 0) {
716edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        trail -= DIVISOR;
717edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        ++lead;
718edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }
719edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    if (convert_top) {
720edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        if (lead == 0 && trail < 0)
721edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            pt = _add("-0", pt, ptlim, modifier);
722c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes        else    pt = _conv(lead, getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
723edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }
724edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    if (convert_yy)
725c1a6a7256026431a9ae49ef2a6139ea99410819bElliott Hughes        pt = _conv(((trail < 0) ? -trail : trail), getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
726edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    return pt;
7271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
728