C++ Convert time ET to CET or something else - c++

I'm parsing files with date and time in it.
Let's say i have the date and time in the following format:
2009/07/18 10:48:39 CET (value in txt-file)
This is in ET:
2009/07/18 4:48:39 ET (could also be the value i parsed)
Is there a solution to convert between the times/dates? Maybe boost?
Couldn't find helpful infos in the boost docs.
Let's say i want to from CET to ET or ET to EST or CET to EST in c++, what would you do?

strftime allows you to print out a struct tm* object using datetime formatting characters (%Y, %m, %d, etc).
What you could do is load a struct tm* object up by parsing your input data (assuming it's regular, this shouldn't require a lot of code), then modify the individual parts of the tm struct with some custom logic based on your timezone conversion (add hour, then check if you need to update day based on new hour value), then print this datetime value in the format you'd like via strftime. Not nearly as simple as the strptime/strftime functions available in php, but a solution nonetheless.

I recommend https://github.com/google/cctz
Also note that "CET" and "ET" are not real time zone identifiers. They may be abbreviations for some time zone, but they do not uniquely identity an actual time zone. If you have some control over the data in the file, you should change "CET" and "ET" to numeric UTC offset values, such as those produced by %z from strftime() (and cctz::Format()). A numeric UTC offset and the Y/M/D H:M:S fields will let you correctly parse out the exact time instant.

Related

Storing unix timestamp as an IntegerField [duplicate]

Which one is best to use, DateTime or INT (Unix Timestamp) or anything else to store the time value?
I think INT will be better at performance and also more universal, since it can be easily converted to many timezones. (my web visitors from all around the world can see the time without confusion)
But, I'm still doubt about it.
Any suggestions?
I wouldn't use INT or TIMESTAMP to save your datetime values. There is the "Year-2038-Problem"! You can use DATETIME and save your datetimes for a long time.
With TIMESTAMP or numeric column types you can only store a range of years from 1970 to 2038. With the DATETIME type you can save dates with years from 1000 to 9999.
It is not recommended to use a numeric column type (INT) to store datetime information. MySQL (and other sytems too) provides many functions to handle datetime information. These functions are faster and more optimized than custom functions or calculations: https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html
To convert the timezone of your stored value to the client timezone you can use CONVERT_TZ. In this case you need to know the timezone of the server and the timezone of your client. To get the timezone of the server you can see some possibilites on this question.
Changing the client time zone The server interprets TIMESTAMP values
in the client’s current time zone, not its own. Clients in different
time zones should set their zone so that the server can properly
interpret TIMESTAMP values for them.
And if you want to get the time zone that a certain one you can do this:
CONVERT_TZ(#dt,'US/Central','Europe/Berlin') AS Berlin,
I wouldn't store it in int, you should check out MySQL Cookbook by Paul DuBois he covers lot's of things in it.Also there is a big portion about your quetion.

Determine if daylight savings applies to a certain date

I'm attempting to modify the creation dates of files to the date they were released. I'm first converting a string such as "2 April 2005" into a std::tm. I then create a SYSTEMTIME as follows:
std::tm dt = from_string("2 April 2005");
SYSTEMTIME st { 0 };
st.wYear = dt.tm_year + 1900; // dt is years from 1900
st.wMonth = dt.tm_mon + 1; // dt is month index 0
st.wDay = dt.tm_mday;
st.wHour = 6; // FILETIME is based on UTC, which is 6 hours ahead
Afterwards I convert the SYSTEMTIME to a FILETIME and use that to apply the changes.
This sets the file time to 2 April 2005 12:00:00 AM which is correct. However, videos after April 2nd were being set to 1:00:00 AM and sure enough, daylight savings happened on April 3rd 2005.
How can I determine if a certain date is before or after daylight savings so I can adjust st.wHour accordingly? The goal is to have all times set to 12:00:00 AM. Preferably this would work on dates dating back to the 60s as well as current.
I tried using TIME_ZONE_INFORMATION and GetTimeZoneInformation but I only get back TIME_ZONE_ID_STANDARD.
A few things:
SYSTEMTIME is just a plain structure. It has separate fields for year, month, day-of-week, day (of month), hour, minute, second and millisecond. It is not either UTC or local time, or anything else by itself. That doesn't come into consideration until you pass it into a function.
FILETIME is another plain structure. It represents the number of 100-nanosecond intervals since midnight of 1601-01-01. Much of the docs would make you think it is always in UTC, but there are functions like FileTimeToLocalFileTime that disprove that. Thus, like SYSTEMTIME, it is up to each individual function to decide how to interpret it.
The SystemTimeToFileTime function accepts a pointer to a SYSTEMTIME that is interpreted as UTC, and returns a pointer to a FILETIME that is also in terms of UTC. There is no local time zone involved.
Don't try to adjust for local time yourself (st.wHour = 6 in your code). The hour will need to vary depending both on time zone and on DST.
You didn't see any response from GetTimeZoneInformation other than TIME_ZONE_STANDARD, because that tells you what is currently in effect - which is disconnected from the dates you might be working with.
You shouldn't be trying to figure out how to adjust for DST on your own. DST is not universally applicable, and it's not always one hour offset. Instead, use a function that converts from the time zone you care about to UTC.
Ultimately it sounds like you are asking about how to set the file time to midnight of the local time zone on a particular date. Thus, I suggest you go through these steps:
Construct a SYSTEMTIME with the date you care about and the time components set to zeros (the default).
Get the local time zone using the GetDynamicTimeZoneInformation function. You want the "dynamic" version such that any historical differences in rules for standard time and DST that Windows knows about are taken into consideration, rather than just the current set of rules.
Pass those two values to the TzSpecificLocalTimeToSystemTimeEx function. It will interpret the input time as being in the input time zone (which was the system's local time zone). The result is a FILETIME that is in terms of UTC.
Pass that value to SetFileTime, which expects the input in terms of UTC.
Also, keep in mind that not all file systems track file times in the same way:
NTFS stores the actual UTC time, so you can move files between computers and the timestamp represents the same point in Universal Time even if the computers have different time zone settings.
FAT and its variants store local time. So when you call SetFileTime, Windows translates from UTC to the local time zone and writes the result. If you then open the file on a system with a different time zone, the date will be interpreted in that time zone, resulting in a different UTC time. (This is often seen on USB sticks, memory cards, etc. when moving files from cameras to computers.)
Lastly, you said:
... Preferably this would work on dates dating back to the 60s as well as current.
Unfortunately, Windows time zones do not track historical dates that far. Microsoft's time zone policy is to track time zone and DST rules for 2010 and forward for all populated places on Earth. Although, several time zones track some historical changes from before 2010 as artifacts from before this policy was formalized. (They are accurate within a given zone, just not uniform in starting years across all zones).
If historical dates are significant to your application, you'll need a very different approach - one that doesn't use the Windows time zone data, but instead uses the IANA time zone database. (More on these in the timezone tag wiki.) Here are some ideas you could explore:
The ICU project has time zone support and a C implementation. It's a bit heavy for this one purpose, but good if you are using it for other localization aspects of an application.
Howard Hinnant (who commented on the question above) has an excellent Date library with IANA time zone support.
It might be possible to get what you need from the Windows.Globalization.Calendar UWP class. I haven't tested to see if it will use historical rules from IANA data or if it uses the Windows data. (If I get a chance to check, I'll come back and update this answer.)
Keep in mind that the IANA database only guarantees from 1970 forward. You said you needed from 1960, and though there are some zones with data for that (and some much older), there is no guarantee of correctness in that period.

How to convert UDate from one timezone to another using ICU

After spending some significant amount of time, I could not figure out how to convert UDate from one timezone to another. Here is the problem I am trying to solve :
I have a timestamp which is number of milliseconds since epoch. This is a timestamp in UTC. I want to convert this timestamp to a timestamp at some local time zone (e.g. US/Eastern). I want to extract number of days since epoch and number of milliseconds since from converted timestamp. I want to use icu library to do this.
I tried to create a UDate from number of milliseconds since epoch in UTC. I can create a timezone instance for the given timezone.
TimeZone *tz = TimeZone::createTimeZone("US/Eastern");
How do I convert UDate from UTC to the given timezone and extract the answers I want? Could it be done using icu?
Any help will be greatly appreciated.
I want … number of days since epoch and number of milliseconds since from converted timestamp.
I think these will be the same regardless of time zone, won't they?
Or can you give an example of the result you would like to see (before vs. after)

What is the right way to convert into UNIX timestamp from the date and time in C/C++?

I have a lot of dates with time in this format:
day.mon.year - hour:min:sec
And I need to convert this dates with time into Unix timestamp.
I used tm structure, but I can't fill those fields:
tm_wday
tm_yday
And I don't must I fill those field, because I don't know do this field have any effect to the value of Unix timestamp.
Help me to choose rigth way to calculate Unix timestamp.
P.S. Dates with time aren't current, they can be date of the 20-th century or future dates (to 2038 year).
P.P.S. I use OS Windows.
POSIX has a formula for exactly what you want:
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_15
tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 +
(tm_year-70)*31536000 + ((tm_year-69)/4)*86400 -
((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400
This works whenever you have a broken-down time in GMT, even if the underlying system's mktime, etc. functions do not use the same format time_t as "Unix timestamps".
If your original time is in local time, you can use mktime and gmtime to convert it to GMT using the system's notion of timezone rules. If you want to apply your own timezone offset rules, just do that manually before using the above formula.
If you are on unix, mktime() will get the second part of the timestamp. It ignores the tm_wday and tm_yday fields.

Date/Time parsing in C++

While doing the data/time parsing in c++ (converting a string in any format to a date), i found the following useful methods
1) strptime() - here the %d, %m etc can have either 1 or 2 characters. The function will take care of that. As a result of this it will enforce that we use a separator between two conversion specifiers. Ex: Its not valid to give %d%m it has be to %d/%m or any other separator. Also this does not support timezones.
2) Boost date IO - here the %d, %m has to have 2 characters. Now, the input string i get is not guaranteed to have this. As a result, its not possible to use this successfully. However, this does seem to support timezone, but not sure. because it says for inputs it does support timezone
So i am planning to use both in conjunction to determine the date. But i would like to get one where i can take into account the timezone as well. But none seems to be supporting that.
Does anybody have a suggestion?
Rgds,
AJ
#AJ: Added another answer so the code gets formatted
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
int
main(void)
{
struct tm tm[1] = {{0}};
strptime("Tue, 19 Feb 2008 20:47:53 +0530", "%a, %d %b %Y %H:%M:%S %z", tm);
fprintf(stdout, "off %ld\n", tm->tm_gmtoff);
return 0;
}
And a run looks like (glibc 2.10.1):
freundt#clyde:pts/28:~/temp> ./test
off 19800
Depends on the libc version, I'd say, and of course what you mean by `taking into account': Is it supposed to read the additional info and then ignore it, is it supposed to store the parsed info in the tm struct, or is it meant to convert to system/environment time?
glibc 2.10.1's strptime() does time zones, from the info page
`%z'
The offset from GMT in ISO 8601/RFC822 format.
`%Z'
The timezone name.
_Note:_ Currently, this is not fully implemented. The format
is recognized, input is consumed but no field in TM is set.
As you noticed strptime doesn't directly support timezones. All it does is read formatted timezone-less data into a tm structure. You'll have to parse an optional timezone indicator yourself (unless it's fixed), and then set TZ and use mktime to convert into a time_t. If you set tm.is_dst to -1 you can even ask that mktime try to figure out the DST for you automatically.
Alternately you could construct your own parser using steams (boost supports a few formats, but may not be general enough). Again like above you can use mktime to compose a time_t.