#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define YYYYMMDDhhmmss 0
#define YYMMDDhhmmss 1
#define ssmmhhDDMMYYYY 2
#define ssmmhhDDMMYY 3
int chars_to_int(const char * s, unsigned int n)
{
int rv = 0;
while (n--)
{
if (*s >= 48 && *s <= 57)
{
rv = 10 * rv + (*s-48);
}
else if (*s == 32)
{
// gently handle space
rv *= 10;
}
else
{
return -1;
}
++s;
}
return rv;
}
/**
* Convert a string in one of the following formats into a (possibly negative) offset of seconds.
* +hhmm
* -hhmm
* 2Bhhmm
* 2Dhhmm
* 2bhhmm
* 2dhhmm
*
* where h and m are digits representing hours and minutes
*
* @param input String in one of the formats
* @return true and the offset in seconds if input matches one of the formats
* false and 0 if it does not
*/
int string_to_offset(const char * input)
{
int offset = 0;
int sign = 0;
if (len == 5)
{
offset = 1;
if (input[0] == '+')
{
// +hhmm
sign = +1;
}
else if (input[0] == '-')
{
// -hhmm
sign = -1;
}
}
else if (len == 6 && input[0] == '2')
{
offset = 2;
if (input[1] == 'B' || input[1] == 'b')
{
// 2Bhhmm or 2bhhmm
sign = +1;
}
if (input[1] == 'D' || input[1] == 'd')
{
// 2Dhhmm or 2Dhhmm
sign = -1;
}
}
if (offset != 0 && sign != 0)
{
return (sign * (3600 * chars_to_int(input+offset,2) + 60 * chars_to_int(input+offset+2, 2)));
}
else
{
return -1;
}
}
// Return the current century.
int current_century()
{
int current_century = -1;
if (current_century == -1)
{
time_t rawtime;
struct tm * timeinfo;
current_century = (1900+timeinfo->tm_year)/100;
}
return current_century;
}
// Return the current year.
int current_year()
{
int current_year = -1;
if (current_year == -1)
{
time_t rawtime;
struct tm * timeinfo;
current_year = 1900+timeinfo->tm_year;
}
return current_year;
}
/**
* Add a century to a year, so that the year is max 20 years in the future and max 80 years in the past
*
* @param year The last two digits of the year
* @return The four digit year as int.
*/
int add_century(int year)
{
static const int yearsInFuture = 20;
int currentYear = current_year();
int proposedYear = year + 100*current_century();
if (proposedYear - currentYear > yearsInFuture)
{
// Too far in future, e.g. current year = 2101, year = 99 (proposedYear = 2199)
proposedYear = proposedYear - 100;
}
else if (currentYear - proposedYear > 100 - yearsInFuture)
{
// Too far in the past, e.g. current year = 2099, year = 00 (proposedYear = 2000)
proposedYear = proposedYear + 100;
}
return proposedYear;
}
/**
* Converts a string representing a local date/time to the native time_t type.
* The timezone of the date/time string is indicated by the timezone string which
* may either be in [+-]hhmm or 2[bBdD]hhmm format or may be any timezone recognized
* by the underlying C-library (e.g. "GMT+2").
*
* @param time The string representing the date/time.
* @param timezone The offset compared to UTC represented by the time or the timezone time refers to
* @param format The format in which the date/time is stored in the string
* @return The time in native time_t type
*/
time_t localtime_to_time_t
(const char * time, const char * timezone
, int format
){
//time_t rv;
//////////////
struct tm timeinfo;
switch (format)
{
case YYYYMMDDhhmmss:
timeinfo.
tm_year = chars_to_int
(time + 0, 4) - 1900; timeinfo.
tm_mon = chars_to_int
(time + 4, 2) - 1; timeinfo.
tm_mday = chars_to_int
(time + 6, 2); timeinfo.
tm_hour = chars_to_int
(time + 8, 2); timeinfo.
tm_min = chars_to_int
(time + 10, 2); timeinfo.
tm_sec = chars_to_int
(time + 12, 2); break;
case YYMMDDhhmmss:
timeinfo.
tm_year = add_century
(chars_to_int
(time + 0, 2)) - 1900; timeinfo.
tm_mon = chars_to_int
(time + 2, 2) - 1; timeinfo.
tm_mday = chars_to_int
(time + 4, 2); timeinfo.
tm_hour = chars_to_int
(time + 6, 2); timeinfo.
tm_min = chars_to_int
(time + 8, 2); timeinfo.
tm_sec = chars_to_int
(time + 10, 2); break;
case ssmmhhDDMMYYYY:
timeinfo.
tm_sec = chars_to_int
(time, 2); timeinfo.
tm_min = chars_to_int
(time + 2, 2); timeinfo.
tm_hour = chars_to_int
(time + 4, 2); timeinfo.
tm_mday = chars_to_int
(time + 6, 2); timeinfo.
tm_mon = chars_to_int
(time + 8, 2) - 1; timeinfo.
tm_year = chars_to_int
(time + 10, 4) - 1900; break;
case ssmmhhDDMMYY:
timeinfo.
tm_sec = chars_to_int
(time, 2); timeinfo.
tm_min = chars_to_int
(time + 2, 2); timeinfo.
tm_hour = chars_to_int
(time + 4, 2); timeinfo.
tm_mday = chars_to_int
(time + 6, 2); timeinfo.
tm_mon = chars_to_int
(time + 8, 2) - 1; timeinfo.
tm_year = add_century
(chars_to_int
(time + 0, 2)) - 1900; break;
}
printf("%d\n", timeinfo.
tm_mday);
/////////////
timeinfo.tm_isdst = -1;
int timezone_offset = string_to_offset(timezone);
if (timezone_offset) {
printf("%d\n", timezone_offset
); }
if (timezone_offset > -1)
{
// timezone is an offset
// TZEnv utc("UTC");
//////////////////////////
//char dup_tz[strlen(tz) + 1];
//strcpy(dup_tz, tz);
//puts(dup_tz);
if (tz) {
}
//setenv("TZ", "", 1); // TZ empty refers to UTC
//tzset();
///////////////////////////
// errno = 0;
// rv = mktime(&timeinfo) - timezone_offset;
// int saved_errno = errno;
// setenv("TZ", dup_tz, 1);
// errno = saved_errno;
} else {
return 99999;
}
//if (rv == -1) return -1;
return 0;
}
int main(void) {
time_t epoch = localtime_to_time_t("181218213533", "2b0200", YYMMDDhhmmss);
printf("%lld\n", (long long) epoch
);
return 0;
}
I2RlZmluZSBfUE9TSVhfQ19TT1VSQ0UgMjAwODA5TAojaW5jbHVkZSA8ZXJybm8uaD4KCiNpbmNsdWRlIDx0aW1lLmg+CiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KCiNkZWZpbmUgWVlZWU1NRERoaG1tc3MgMAojZGVmaW5lIFlZTU1ERGhobW1zcyAxCiNkZWZpbmUgc3NtbWhoRERNTVlZWVkgMgojZGVmaW5lIHNzbW1oaERETU1ZWSAzCgppbnQgY2hhcnNfdG9faW50KGNvbnN0IGNoYXIgKiBzLCB1bnNpZ25lZCBpbnQgbikKewoJaW50IHJ2ID0gMDsKCXdoaWxlIChuLS0pCgl7CgkJaWYgKCpzID49IDQ4ICYmICpzIDw9IDU3KQoJCXsKCQkJcnYgPSAxMCAqIHJ2ICsgKCpzLTQ4KTsKCQl9CgkJZWxzZSBpZiAoKnMgPT0gMzIpCgkJewoJCQkvLyBnZW50bHkgaGFuZGxlIHNwYWNlCgkJCXJ2ICo9IDEwOwoJCX0KCQllbHNlCgkJewoJCQlyZXR1cm4gLTE7CgkJfQoJCSsrczsKCX0KCXJldHVybiBydjsKfQoKLyoqCiAqIENvbnZlcnQgYSBzdHJpbmcgaW4gb25lIG9mIHRoZSBmb2xsb3dpbmcgZm9ybWF0cyBpbnRvIGEgKHBvc3NpYmx5IG5lZ2F0aXZlKSBvZmZzZXQgb2Ygc2Vjb25kcy4KICogK2hobW0KICogLWhobW0KICogMkJoaG1tCiAqIDJEaGhtbQogKiAyYmhobW0KICogMmRoaG1tCiAqCiAqIHdoZXJlIGggYW5kIG0gYXJlIGRpZ2l0cyByZXByZXNlbnRpbmcgaG91cnMgYW5kIG1pbnV0ZXMKICoKICogQHBhcmFtIGlucHV0IFN0cmluZyBpbiBvbmUgb2YgdGhlIGZvcm1hdHMKICogQHJldHVybiB0cnVlIGFuZCB0aGUgb2Zmc2V0IGluIHNlY29uZHMgaWYgaW5wdXQgbWF0Y2hlcyBvbmUgb2YgdGhlIGZvcm1hdHMKICogICAgICAgICBmYWxzZSBhbmQgMCBpZiBpdCBkb2VzIG5vdAogKi8KaW50IHN0cmluZ190b19vZmZzZXQoY29uc3QgY2hhciAqIGlucHV0KQp7CglpbnQgbGVuID0gc3RybGVuKGlucHV0KTsKCWludCBvZmZzZXQgPSAwOwoJaW50IHNpZ24gPSAwOwoJaWYgKGxlbiA9PSA1KQoJewoJCW9mZnNldCA9IDE7CgkJaWYgIChpbnB1dFswXSA9PSAnKycpCgkJewoJCQkvLyAraGhtbQoJCQlzaWduID0gKzE7CgkJfQoJCWVsc2UgaWYgKGlucHV0WzBdID09ICctJykKCQl7CgkJCS8vIC1oaG1tCgkJCXNpZ24gPSAtMTsKCQl9Cgl9CgllbHNlIGlmIChsZW4gPT0gNiAmJiBpbnB1dFswXSA9PSAnMicpCgl7CgkJb2Zmc2V0ID0gMjsKCQlpZiAoaW5wdXRbMV0gPT0gJ0InIHx8IGlucHV0WzFdID09ICdiJykKCQl7CgkJCS8vIDJCaGhtbSBvciAyYmhobW0KCQkJc2lnbiA9ICsxOwoJCX0KCQlpZiAoaW5wdXRbMV0gPT0gJ0QnIHx8IGlucHV0WzFdID09ICdkJykKCQl7CgkJCS8vIDJEaGhtbSBvciAyRGhobW0KCQkJc2lnbiA9IC0xOwoJCX0KCX0KCglpZiAob2Zmc2V0ICE9IDAgJiYgc2lnbiAhPSAwKQoJewoJCXJldHVybiAoc2lnbiAqICgzNjAwICogY2hhcnNfdG9faW50KGlucHV0K29mZnNldCwyKSArIDYwICogY2hhcnNfdG9faW50KGlucHV0K29mZnNldCsyLCAyKSkpOwoJfQoJZWxzZQoJewoJCXJldHVybiAtMTsKCX0KfQoKLy8gUmV0dXJuIHRoZSBjdXJyZW50IGNlbnR1cnkuCmludCBjdXJyZW50X2NlbnR1cnkoKQp7CglpbnQgY3VycmVudF9jZW50dXJ5ID0gLTE7CgoJaWYgKGN1cnJlbnRfY2VudHVyeSA9PSAtMSkKCXsKCQl0aW1lX3QgcmF3dGltZTsKCQl0aW1lICggJnJhd3RpbWUgKTsKCQlzdHJ1Y3QgdG0gKiB0aW1laW5mbzsKCQl0aW1laW5mbyA9IGxvY2FsdGltZSAoICZyYXd0aW1lICk7CgkJY3VycmVudF9jZW50dXJ5ID0gKDE5MDArdGltZWluZm8tPnRtX3llYXIpLzEwMDsKCX0KCglyZXR1cm4gY3VycmVudF9jZW50dXJ5Owp9CgovLyBSZXR1cm4gdGhlIGN1cnJlbnQgeWVhci4KaW50IGN1cnJlbnRfeWVhcigpCnsKCWludCBjdXJyZW50X3llYXIgPSAtMTsKCglpZiAoY3VycmVudF95ZWFyID09IC0xKQoJewoJCXRpbWVfdCByYXd0aW1lOwoJCXRpbWUgKCAmcmF3dGltZSApOwoJCXN0cnVjdCB0bSAqIHRpbWVpbmZvOwoJCXRpbWVpbmZvID0gbG9jYWx0aW1lICggJnJhd3RpbWUgKTsKCQljdXJyZW50X3llYXIgPSAxOTAwK3RpbWVpbmZvLT50bV95ZWFyOwoJfQoKCXJldHVybiBjdXJyZW50X3llYXI7Cn0KCi8qKgogKiBBZGQgYSBjZW50dXJ5IHRvIGEgeWVhciwgc28gdGhhdCB0aGUgeWVhciBpcyBtYXggMjAgeWVhcnMgaW4gdGhlIGZ1dHVyZSBhbmQgbWF4IDgwIHllYXJzIGluIHRoZSBwYXN0CiAqCiAqIEBwYXJhbSB5ZWFyIFRoZSBsYXN0IHR3byBkaWdpdHMgb2YgdGhlIHllYXIKICogQHJldHVybiBUaGUgZm91ciBkaWdpdCB5ZWFyIGFzIGludC4KICovCmludCBhZGRfY2VudHVyeShpbnQgeWVhcikKewoJc3RhdGljIGNvbnN0IGludCB5ZWFyc0luRnV0dXJlID0gMjA7CgoJaW50IGN1cnJlbnRZZWFyID0gY3VycmVudF95ZWFyKCk7CglpbnQgcHJvcG9zZWRZZWFyID0geWVhciArIDEwMCpjdXJyZW50X2NlbnR1cnkoKTsKCWlmIChwcm9wb3NlZFllYXIgLSBjdXJyZW50WWVhciA+IHllYXJzSW5GdXR1cmUpCgl7CgkJLy8gVG9vIGZhciBpbiBmdXR1cmUsIGUuZy4gY3VycmVudCB5ZWFyID0gMjEwMSwgeWVhciA9IDk5IChwcm9wb3NlZFllYXIgPSAyMTk5KQoJCXByb3Bvc2VkWWVhciA9IHByb3Bvc2VkWWVhciAtIDEwMDsKCX0KCWVsc2UgaWYgKGN1cnJlbnRZZWFyIC0gcHJvcG9zZWRZZWFyID4gMTAwIC0geWVhcnNJbkZ1dHVyZSkKCXsKCQkvLyBUb28gZmFyIGluIHRoZSBwYXN0LCBlLmcuIGN1cnJlbnQgeWVhciA9IDIwOTksIHllYXIgPSAwMCAocHJvcG9zZWRZZWFyID0gMjAwMCkKCQlwcm9wb3NlZFllYXIgPSBwcm9wb3NlZFllYXIgKyAxMDA7Cgl9CgoJcmV0dXJuIHByb3Bvc2VkWWVhcjsKfQoKLyoqCiAqIENvbnZlcnRzIGEgc3RyaW5nIHJlcHJlc2VudGluZyBhIGxvY2FsIGRhdGUvdGltZSB0byB0aGUgbmF0aXZlIHRpbWVfdCB0eXBlLgogKiBUaGUgdGltZXpvbmUgb2YgdGhlIGRhdGUvdGltZSBzdHJpbmcgaXMgaW5kaWNhdGVkIGJ5IHRoZSB0aW1lem9uZSBzdHJpbmcgd2hpY2gKICogbWF5IGVpdGhlciBiZSBpbiBbKy1daGhtbSBvciAyW2JCZERdaGhtbSBmb3JtYXQgb3IgbWF5IGJlIGFueSB0aW1lem9uZSByZWNvZ25pemVkCiAqIGJ5IHRoZSB1bmRlcmx5aW5nIEMtbGlicmFyeSAoZS5nLiAiR01UKzIiKS4KICoKICogQHBhcmFtIHRpbWUgVGhlIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIGRhdGUvdGltZS4KICogQHBhcmFtIHRpbWV6b25lIFRoZSBvZmZzZXQgY29tcGFyZWQgdG8gVVRDIHJlcHJlc2VudGVkIGJ5IHRoZSB0aW1lIG9yIHRoZSB0aW1lem9uZSB0aW1lIHJlZmVycyB0bwogKiBAcGFyYW0gZm9ybWF0IFRoZSBmb3JtYXQgaW4gd2hpY2ggdGhlIGRhdGUvdGltZSBpcyBzdG9yZWQgaW4gdGhlIHN0cmluZwogKiBAcmV0dXJuIFRoZSB0aW1lIGluIG5hdGl2ZSB0aW1lX3QgdHlwZQogKi8KdGltZV90IGxvY2FsdGltZV90b190aW1lX3QoY29uc3QgY2hhciAqIHRpbWUsIGNvbnN0IGNoYXIgKiB0aW1lem9uZSwgaW50IGZvcm1hdCkKewoJLy90aW1lX3QgcnY7CiAgICAKICAgIC8vLy8vLy8vLy8vLy8vCiAgICBzdHJ1Y3QgdG0gdGltZWluZm87CiAgICBzd2l0Y2ggKGZvcm1hdCkKCQl7CgkJY2FzZSBZWVlZTU1ERGhobW1zczoKCQkJaWYgKHN0cmxlbih0aW1lKSA8IDE0KSByZXR1cm4gMDsKCQkJdGltZWluZm8udG1feWVhciA9IGNoYXJzX3RvX2ludCh0aW1lICsgMCwgNCkgLSAxOTAwOwoJCQl0aW1laW5mby50bV9tb24gID0gY2hhcnNfdG9faW50KHRpbWUgKyA0LCAyKSAtIDE7CgkJCXRpbWVpbmZvLnRtX21kYXkgPSBjaGFyc190b19pbnQodGltZSArIDYsIDIpOwoJCQl0aW1laW5mby50bV9ob3VyID0gY2hhcnNfdG9faW50KHRpbWUgKyA4LCAyKTsKCQkJdGltZWluZm8udG1fbWluICA9IGNoYXJzX3RvX2ludCh0aW1lICsgMTAsIDIpOwoJCQl0aW1laW5mby50bV9zZWMgID0gY2hhcnNfdG9faW50KHRpbWUgKyAxMiwgMik7CgkJCWJyZWFrOwoJCWNhc2UgWVlNTUREaGhtbXNzOgoJCQlpZiAoc3RybGVuKHRpbWUpIDwgMTIpIHJldHVybiAwOwoJCQl0aW1laW5mby50bV95ZWFyID0gYWRkX2NlbnR1cnkoY2hhcnNfdG9faW50KHRpbWUgKyAwLCAyKSkgLSAxOTAwOwoJCQl0aW1laW5mby50bV9tb24gID0gY2hhcnNfdG9faW50KHRpbWUgKyAyLCAyKSAtIDE7CgkJCXRpbWVpbmZvLnRtX21kYXkgPSBjaGFyc190b19pbnQodGltZSArIDQsIDIpOwoJCQl0aW1laW5mby50bV9ob3VyID0gY2hhcnNfdG9faW50KHRpbWUgKyA2LCAyKTsKCQkJdGltZWluZm8udG1fbWluICA9IGNoYXJzX3RvX2ludCh0aW1lICsgOCwgMik7CgkJCXRpbWVpbmZvLnRtX3NlYyAgPSBjaGFyc190b19pbnQodGltZSArIDEwLCAyKTsKCQkJcHV0cygiaGVyZSIpOwoJCQlicmVhazsKCQljYXNlIHNzbW1oaERETU1ZWVlZOgoJCQlpZiAoc3RybGVuKHRpbWUpIDwgMTQpIHJldHVybiAwOwoJCQl0aW1laW5mby50bV9zZWMgID0gY2hhcnNfdG9faW50KHRpbWUsIDIpOwoJCQl0aW1laW5mby50bV9taW4gID0gY2hhcnNfdG9faW50KHRpbWUgKyAyLCAyKTsKCQkJdGltZWluZm8udG1faG91ciA9IGNoYXJzX3RvX2ludCh0aW1lICsgNCwgMik7CgkJCXRpbWVpbmZvLnRtX21kYXkgPSBjaGFyc190b19pbnQodGltZSArIDYsIDIpOwoJCQl0aW1laW5mby50bV9tb24gID0gY2hhcnNfdG9faW50KHRpbWUgKyA4LCAyKSAtIDE7CgkJCXRpbWVpbmZvLnRtX3llYXIgPSBjaGFyc190b19pbnQodGltZSArIDEwLCA0KSAtIDE5MDA7CgkJCWJyZWFrOwoJCWNhc2Ugc3NtbWhoRERNTVlZOgoJCQlpZiAoc3RybGVuKHRpbWUpIDwgMTIpIHJldHVybiAwOwoJCQl0aW1laW5mby50bV9zZWMgID0gY2hhcnNfdG9faW50KHRpbWUsIDIpOwoJCQl0aW1laW5mby50bV9taW4gID0gY2hhcnNfdG9faW50KHRpbWUgKyAyLCAyKTsKCQkJdGltZWluZm8udG1faG91ciA9IGNoYXJzX3RvX2ludCh0aW1lICsgNCwgMik7CgkJCXRpbWVpbmZvLnRtX21kYXkgPSBjaGFyc190b19pbnQodGltZSArIDYsIDIpOwoJCQl0aW1laW5mby50bV9tb24gID0gY2hhcnNfdG9faW50KHRpbWUgKyA4LCAyKSAtIDE7CgkJCXRpbWVpbmZvLnRtX3llYXIgPSBhZGRfY2VudHVyeShjaGFyc190b19pbnQodGltZSArIDAsIDIpKSAtIDE5MDA7CgkJCWJyZWFrOwogICAgfQogICAgCiAgICBwcmludGYoIiVkXG4iLCB0aW1laW5mby50bV9tZGF5KTsKICAgIAogICAgLy8vLy8vLy8vLy8vLwoJCgl0aW1laW5mby50bV9pc2RzdCA9IC0xOwoJaW50IHRpbWV6b25lX29mZnNldCA9IHN0cmluZ190b19vZmZzZXQodGltZXpvbmUpOwoJaWYgKHRpbWV6b25lX29mZnNldCkgewoJCXByaW50ZigiJWRcbiIsIHRpbWV6b25lX29mZnNldCk7Cgl9CgkKCQoJaWYgKHRpbWV6b25lX29mZnNldCA+IC0xKQoJewoJCS8vIHRpbWV6b25lIGlzIGFuIG9mZnNldAoJCS8vIFRaRW52IHV0YygiVVRDIik7CgkJCgkJLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KCQljaGFyICAgKnR6ID0gZ2V0ZW52KCJUWiIpOwoJCS8vY2hhciBkdXBfdHpbc3RybGVuKHR6KSArIDFdOwoJCS8vc3RyY3B5KGR1cF90eiwgdHopOwoJCS8vcHV0cyhkdXBfdHopOwoJaWYgKHR6KSB7CgkJCgl9CgogICAgLy9zZXRlbnYoIlRaIiwgIiIsIDEpOyAvLyBUWiBlbXB0eSByZWZlcnMgdG8gVVRDCiAgICAvL3R6c2V0KCk7CgoKCQkvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KCQkKCS8vCWVycm5vID0gMDsKCSAvLyAgIHJ2ID0gbWt0aW1lKCZ0aW1laW5mbykgLSB0aW1lem9uZV9vZmZzZXQ7CgkgLy8gICBpbnQgc2F2ZWRfZXJybm8gPSBlcnJubzsKCSAgICAKICAgICAvLyAgIHNldGVudigiVFoiLCBkdXBfdHosIDEpOwoKCiAgICAvLwllcnJubyA9IHNhdmVkX2Vycm5vOwogICAgCQoJfSBlbHNlIHsKCQlyZXR1cm4gOTk5OTk7Cgl9CgoJLy9pZiAocnYgPT0gLTEpIHJldHVybiAtMTsKCXJldHVybiAwOwp9CgppbnQgbWFpbih2b2lkKSB7CgkKCXRpbWVfdCBlcG9jaCA9IGxvY2FsdGltZV90b190aW1lX3QoIjE4MTIxODIxMzUzMyIsICIyYjAyMDAiLCBZWU1NRERoaG1tc3MpOwoJcHJpbnRmKCIlbGxkXG4iLCAobG9uZyBsb25nKSBlcG9jaCk7CgkKCXJldHVybiAwOwp9Cg==