Working with timezones in C - c

I'm currently migrating some of my code from Cocoa (Apple's Objective-C API) to C, in order to make it available for other operating systems, such as GNU/Linux.
In Cocoa, there were many great things like creating NSTimeZone objects from their string descriptors using timeZoneWithAbbreviation:. This allowed me to use values like "Europe/Paris" to easily create NSTimeZone objects.
Another important method for me was secondsFromGMTForDate: because it automatically considers DST rules for you.
Right now, the closest thing to NSTimeZone I've found for C is the struct timezone (see here). However, I do not see how I can easily get the GMT "offset" in seconds for a specific time and timezone. Neither do I understand how to get timezone structs if you only have a description like "Europe/Paris".

The following is my understanding and may be wrong...
I'm not sure how OS X does it, but on Linux, the standard C timezone functions use the Olson database, which is really quite powerful (since it has a full list of locale descriptions and keeps track of historical time zone rules as well as current rules).
To set a time zone, call tzset. This function is automatically called by other time-related functions, but you can manually specify a different time zone from the system default by setting the TZ environment variable then calling tzset. For example:
int main(int argc, char *argv[]) {
time_t t = time(NULL);
printf("%s\n", ctime(&t));
setenv("TZ", "America/Chicago", 1);
printf("%s\n", ctime(&t));
return 0;
}
Calling tzset also sets the timezone global variable, which you can use to find the GMT offset in seconds for the current time zone.
These functions only let you use one time zone at a time, and although all of this (except for possibly the timezone global variable) should be standard C, platforms other than Linux may not have the full support for lists of locales, daylight savings time changes, etc. If you find that this doesn't meet your needs, then you can try using third-party libraries, such as the code distributed with the [Olson database] or ICU's TimeZone class (also usable from C).

Unfortunately, you are treading into difficult territory. There isn't a good, widely available time zone library not attached to other major projects. You can look at the code that comes with the Olson Database (of time zones), and you can look at ICU (Internationalization Components for Unicode).

Related

Is there a portable way to get the local system timezone into a libical icaltimetype?

libical seems to only accept the Olsen city name to look up timezones in its database.
What I've got that's portable is a struct tm which has a GMT offset and the shorthand 3-4 letter code (EST/EDT etc) but there's no function that accepts that in libical.
I have a really lousy way where I scan the tz list from libical trying to match the tznames, and that will probably work, but I am well aware this is a bad idea. But I haven't found any other way of getting the local timezone into a libical icaltimetype.
Am I missing something simple?
And by portable I mean windows, osx and linux.
This is a c program I'm writing.
But I see now that tz offset is not posix, so that won't do.
So I think the answer is that there is no answer. Nothing portable anyway.
So I have separate build paths for linux and osx, and I haven't gotten to windows yet..
The linux implementation just reads from /etc/timezone (more on that on How do I find the current system timezone?)
and the osx implementation does this.
CFTimeZoneRef tzlocal = CFTimeZoneCopyDefault();
CFStringRef me = CFTimeZoneGetName(tzlocal);
NSString *local = (__bridge NSString *)me;
const char *tzname = [local cStringUsingEncoding:NSUTF8StringEncoding];
log.debug("Looking up timezone for %s", tzname);
// this is a built-in timezone so we don't have to free it.
local_timezone = icaltimezone_get_builtin_timezone(tzname);
Not portable but at least it is correct.

accessing xtime variable Linux kernel

I am implementing system call that will return the current time of the day (for learning purpose).
I have looked at implementations of gettimeofday() on Linux 3.19.2
from the books I checked I got that
The current time of day (the wall time) is defined in kernel/time/timekeeping.c:
struct timespec xtime;
[Linux kernel development Rober Love]
however I couldn't able to get the xtime variable definition in that file.
where is the xtime variable declared in the Linux kernel and how can I access it from my module or my function?
what are the headers I should include?
That reference is obsolete. Recent kernels no longer have xtime. Though there are still some fields in the kernel timekeeping structure with a prefix of xtime_ that I assume are descended from it. See, for example, struct timekeeper in include/linux/timekeeper_internal.h.
You would probably want to stick to the slightly more stable functions defined in include/linux/timekeeping.h

Access locale information

What is the most portable way to access locale information?
I'm interested in time locale data, such as month names, day of week names, local time format etc.
Ideally I'd like a POSIX interface, but if it doesn't exist, glibc-specific one will do.
If possible, getting the information about the locale X shouldn't require setting it (using uselocale() or similar).
Calling strftime() many times with all sorts of parameters is considered a hack, not a solution.
If there's nothing better, I'm willing to consider directly parsing glibc's locale files if there's a reliable way to determine their location.
nl_langinfo is a POSIX-standard interface for returning that information and appears to have available all of the things that you're looking for. Sadly, it does require that you call setlocale before calling it. I don't see an interface that lets you query an arbitrary locale without first making it the current locale.

Get List of Time Zones Across Platforms in C

I am developing a program in C which needs to return an array of strings of all of the possible regions the computer has access to information from (ostensibly from tz database). I need to make this cross-platform between Linux (or at least Ubuntu) and Windows, so any common approaches between the two platforms would make my life much easier. I am aware of a few ways to do it on Windows (through the registry, or the approach described here http://msdn.microsoft.com/en-us/library/ms171251(v=sql.90).aspx), but I haven't been able to find any way of doing this in Linux besides hard coding an array in. What would be the best way to accomplish this in Ubuntu, and is there a better way in Windows than the two I mentioned above?
Dave, the contents of the zoneinfo directory is consistent not only across Linux distros, but also across many (most) other Unices.
The exact location may be different in some cases (I know only one: on Linux, many-many years ago it used to be under /usr/lib/zoneinfo, when there was no such thing as /usr/share), so it should be configurable in your app. But you can use /usr/share/zoneinfo as a default, and it'll work in 99.9% of the cases.
In Linux, would walking the contents of /usr/share/zoneinfo be sufficient?
There is a C++ library (I know you said C but you can write a wrapper...) called ICU which has all the necessary functions to load the list of timezones.
http://icu-project.org/apiref/icu4c/classTimeZone.html
Look for this function to get a complete list (other functions can be used if you'd like to filter the list in some ways):
/**
* Returns an enumeration over all recognized time zone IDs. (i.e.,
* all strings that createTimeZone() accepts)
*
* #return an enumeration object, owned by the caller.
* #stable ICU 2.4
*/
static StringEnumeration* U_EXPORT2 createEnumeration();

time.h drop-in replacement : time_t for values (year < 1970) and (year > 2038) in ANSI-C or C99

I have a piece of code in ANSI C which uses the time.h library and time_h structures to (amongst other date-related calculations) work out the interval between two given dates. This works fine but this limits my code to input between 1970 and 2038. I would now like to make my code more general.
Is there a common C library (ANSI or C99 standard) which implements date calculations on ranges larger than time.h, on a granularity of 1 day (i.e. I need to-the-day resolution but hour resolution is not necessary)?
(I'm adapting the code to deal with historical events hence it would be nice if it could also deal with dates in B.C. ....)
Yes, the y2038 project is reimplementing time.h to be 2038 safe. So far gmtime(), localtime(), mktime() and gmtime() are done and well tested. Those were the hard bits. It spans about 300 billion years in either direction.
There's a public domain implementation used in SQLite: documentation, source
I've also found the Calendar FAQ useful; this page pops up early on Google.

Resources