Reputation: 1825
I am trying to make an easily accessible TimeDate variable, but am having problems with conversion. In time.h, how would I convert time_t (seconds since 1/1/1970), into the current local timezone (compensating for daylight savings time if applicable), so that:
time_t Seconds;
Becomes:
struct TimeDate
{
short YYYY;
unsigned char MM;
unsigned char DD;
unsigned char HH; //Non-DST, non-timezone, IE UTC (user has to add DST and TZO to get what they need)
unsigned char MM;
unsigned char S;
char TZ[4]; //This can be optionally a larger array, null terminated preferably
char TZO; //Timezone Offset from UTC
char DST; //Positive is DST (and amount of DST to apply), 0 is none, negative is unknown/error
};
Without using any string literals (bar for the timezone name) in the process (to keep it efficient)? This is also taking into account leap years. Bonus if TimeDate can be converted back into time_t.
Upvotes: 2
Views: 3992
Reputation: 881153
The C standard library (accessible in C++ by using ctime
) provides localtime
for exactly that purpose (or gmtime
for UTC). You could shoe-horn the resultant struct tm
into your own structure after that if there's some reason why the standard one is not sufficient to your needs.
The one thing it doesn't provide is the timezone itself but you can get that (and the offset in ISO 8601 format) by using strftime
with the %Z
and %z
format strings
By way of example, here's a program that demonstrates this in action:
#include <iostream>
#include <cstdlib>
#include <ctime>
int main(void) {
time_t t;
struct tm *tim;
char tz[32];
char ofs[32];
std::system ("date");
std::cout << std::endl;
t = std::time (0);
tim = std::localtime (&t);
std::strftime (tz, sizeof (tz), "%Z", tim);
std::strftime (ofs, sizeof (ofs), "%z", tim);
std::cout << "Year: " << (tim->tm_year + 1900) << std::endl;
std::cout << "Month: " << (tim->tm_mon + 1) << std::endl;
std::cout << "Day: " << tim->tm_mday << std::endl;
std::cout << "Hour: " << tim->tm_hour << std::endl;
std::cout << "Minute: " << tim->tm_min << std::endl;
std::cout << "Second: " << tim->tm_sec << std::endl;
std::cout << "Day of week: " << tim->tm_wday << std::endl;
std::cout << "Day of year: " << tim->tm_yday << std::endl;
std::cout << "DST?: " << tim->tm_isdst << std::endl;
std::cout << "Timezone: " << tz << std::endl;
std::cout << "Offset: " << ofs << std::endl;
return 0;
}
When I run this on my box, I see:
Wed Sep 28 20:45:39 WST 2011
Year: 2011
Month: 9
Day: 28
Hour: 20
Minute: 45
Second: 39
Day of week: 3
Day of year: 270
DST?: 0
Timezone: WST
Offset: +0800
Upvotes: 9