i m new to c.I want to FTP to a system and get the timezone of that system.in c++
There is no way in the FTP standard to do this. You could try uploading a new (small) file and check its date-time as reported by FTP, compared to current local time.
New answer for old question.
Rationale for revisiting this: We have better tools now.
This free, open-source, portable library will get the current time zone setting in terms of the IANA time zone database. On Windows it will convert the Windows timezone into an IANA time zone. Fully documented.
Here's how you print out the name of the current time zone:
#include "tz.h"
#include <iostream>
int
main()
{
std::cout << date::current_zone()->name() << '\n';
}
For me this currently outputs:
America/New_York
You can convert a std::chrono::system_clock to a local time and print it out:
std::cout << date::make_zoned(date::current_zone(),
std::chrono::system_clock::now()) << '\n';
which just output for me:
2016-07-16 19:24:00.447015 EDT
See the github wiki for many more examples.
Related
I would like to store/save time in a file. That's no issue, BUT:
What if a time zone changes? Or daylight time may differ.
How can I compare the saved time in a file with the current time? What if the time zone changes or daylight shifts.
Current time has to be always greater than saved time in order to continue with the program.
Thanks for any advice.
Unix timestamps do not change accross timezones
To avoid timezone changes & other problems with time you can probably use timestamps. In C++ they are available through chrono library.
Example and +/- related question
#include <iostream>
#include <chrono>
int main()
{
const auto p1 = std::chrono::system_clock::now();
std::cout << "seconds since epoch: "
<< std::chrono::duration_cast<std::chrono::seconds>(
p1.time_since_epoch()).count() << '\n';
}
Then if this is enough for you just save timestamp to file and compare with a new timestamp.
Probably you would like to have it in a human readable format. Some useful ways to do this in C++ can be found here
Have a Unix timestamp and I need equivalents of localtime_s, but where I can pass in the timezone. Alternately I'm looking for a way to change the timezone programatically for the app (not the whole system), so that localtime_s returns the correct values.
Strangely enough, if I set TZ environment variable in a shell to GMT, and then launch my application, localtime_s returns values in GMT.
I've tried:
::SetEnvironmentVariable("TZ", "GMT");
tzset();
But it does not change the results of later calls to localtime_s
Note that I'm running the application on Windows 7, using VS 2013.
If you are willing to use a free, open-source 3rd party library, this works on VS-2013. There are many examples on how to use it here:
https://github.com/HowardHinnant/date/wiki/Examples-and-Recipes
For example here is how to output the current time in New York and Chicago:
#include "tz.h"
#include <iostream>
int
main()
{
auto now = std::chrono::system_clock::now();
std::cout << "Current time in New York: "
<< date::make_zoned("America/New_York", now) << '\n';
std::cout << "Current time in Chicago : "
<< date::make_zoned("America/Chicago", now) << '\n';
}
This just output for me:
Current time in New York: 2016-08-12 10:36:24.670966 EDT
Current time in Chicago : 2016-08-12 09:36:24.670966 CDT
I want to get the transition time for DST
Under Linux with giving time zone or TZ env.
My way is stupid, giving the start of the year and try every hour then check tm_isdst value of local time to get the transition time.
Is there some simple way to do this?
There is the source code in glibc, which you can browse here:
http://sourceware.org/git/?p=glibc.git;a=tree;f=timezone
Or you can use the timezone database here:
ftp://ftp.iana.org/tz/releases/tzdata2012c.tar.gz
Since you haven't given a particular timezone/location, I can't look up and give you the exact information for you.
You can also use boost_datetime.
#include <iostream>
#include <boost/date_time/local_time/local_time.hpp>
using namespace boost::local_time;
using namespace boost::posix_time;
int main()
{
tz_database tz_db;
tz_db.load_from_file("/path_to_boost/boost/libs/date_time/data/date_time_zonespec.csv");
time_zone_ptr zone = tz_db.time_zone_from_region("America/New_York");
ptime t1 = zone->dst_local_start_time(2013);
ptime t2 = zone->dst_local_end_time(2013);
std::cout << t1 << std::endl;
std::cout << t2 << std::endl;
}
Some related SO links:
c++ How to find the time in foreign country taking into account daylight saving?
How do you get the timezone (offset) for a location on a particular date?
But as RedX said earlier, politics may change time zones. So actually your original solution has the advantage of being automatically updated with the underlying OS. Also, you can improve your existing solution by using binary search.
I have a setup working using localtime() to get a tm with the local times represented in it. And that is all good.
However, if I change timezone while the application is running, it does not notice that I have changed timezones.
Is there some way to tell it to 'go look again' to refresh to the system timezone?
I know this is probably not a common case, but it is what test are doing to test this feature, so they want it supported!
Take a look at tzset (this is posix only). This might give you what you need. If your TZ environment variable is unset, it should reinitialize from the OS.
From the man page:
DESCRIPTION
The tzset() function initializes the tzname variable from the TZ environment variable. This function is automatically called by the
other time conversion functions that depend on the time zone. In a
SysV-like environment it will also set the variables timezone
(seconds West of GMT) and daylight (0 if this time zone does not
have any daylight savings time rules, non-zero if there is a time
during the year when daylight savings time applies).
If the TZ variable does not appear in the environment, the tzname variable is initialized with the best approximation of local
wall clock time, as specified by the tzfile(5)-format file localtime
found in the system timezone directory (see below). (One also often
sees /etc/localtime used here, a symlink to the right file in the
system timezone directory.)
A simple test:
#include <iostream>
#include <time.h>
#include <stdlib.h>
int main()
{
tzset();
time_t t;
time(&t);
std::cout << "tz: " << tzname[0] << " - " << tzname[1] << " " << ctime(&t) << std::endl;
setenv("TZ", "EST5EDT", 1);
tzset();
std::cout << "tz: " << tzname[0] << " - " << tzname[1] << " " << ctime(&t) << std::endl;
return 0;
}
Gives me output:
tz: CST - CDT Wed Jan 11 12:35:02 2012
tz: EST - EDT Wed Jan 11 13:35:02 2012
There's nothing in the standard library to do this. Unless your platform offers some extension to the library for updating the time zone, your program's calls to localtime() will probably always use the time zone that was active at program start up.
You could probably work around that by putting the localtime stuff in a separate process that your main program can startup and shutdown at will, thus re-initializing that process's time zone.
Or instead your platform may offer some other API for getting the local time that will reflect changes in the system time zone.
In most of the examples I had seen:
time_zone_ptr zone( new posix_time_zone("MST-07") );
But I just want to get the current time zone for the machine that runs the code. I do not want to hard code the time zone name.
Plain posix: call tzset, use tzname.
#include <ctime>
tzset();
time_zone_ptr zone(new posix_time_zone(tzname[localtime(0)->tm_isdst]));
Posix with glibc/bsd additions:
time_zone_ptr zone(new posix_time_zone(localtime(0)->tm_zone));
The above are abbreviated Posix timezones, defined in terms of offset from UTC and not stable over time (there's a longer form that can include DST transitions, but not political and historical transitions).
ICU is portable and has logic for retrieving the system timezone as an Olson timezone (snippet by sumwale):
// Link with LDLIBS=`pkg-config icu-i18n --libs`
#include <unicode/timezone.h>
#include <iostream>
using namespace U_ICU_NAMESPACE;
int main() {
TimeZone* tz = TimeZone::createDefault();
UnicodeString us;
std::string s;
tz->getID(us);
us.toUTF8String(s);
std::cout << "Current timezone ID: " << s << '\n';
delete tz;
}
On Linux, ICU is implemented to be compatible with tzset and looks at TZ and /etc/localtime, which on recent Linux systems is specced to be a symlink containing the Olson identifier (here's the history). See uprv_tzname for implementation details.
Boost doesn't know how to use the Olson identifier. You could build a posix_time_zone using the non-DST and DST offsets, but at this point, it's best to keep using the ICU implementation. See this Boost FAQ.
Quite late in the day, but I was looking for something similar so this can hopefully help others. The following (non-boost) way using strftime seems to work on most platforms:
time_t ts = 0;
struct tm t;
char buf[16];
::localtime_r(&ts, &t);
::strftime(buf, sizeof(buf), "%z", &t);
std::cout << "Current timezone: " << buf << std::endl;
::strftime(buf, sizeof(buf), "%Z", &t);
std::cout << "Current timezone: " << buf << std::endl;
Or one can use std::time_put for a pure C++ version.
Well, maybe you could do it using the GeoIP library. I know it's a bit of an overkill, but since most computers in the world are connected to the internet, you could probably get away with it. According to the guy I'm developing for, it's been over 99% accurate.
Note: This is a dumb idea. I am just stretching for answers.
In order to properly answer this question, it's important to understand that the time zone support in Boost is severely limited.
It's primarily focused on POSIX time zones, which have several limitations. These limitations are discussed in the POSIX section of the timezone tag wiki, so I won't repeat them here.
It has functions that work with IDs of IANA/Olson time zones, but it artificially maps these to POSIX values - which has the effect of flattening the time zone to a single point in history. These mappings are stored in a csv file in the Boost source code.
The csv file hasn't been updated since April 2011, and there have been many changes to time zones since then. So, the mappings it does have are somewhat inaccurate.
In general, I would not recommend Boost for working with time zones. Instead, consider the ICU TimeZone Classes, which are part of the ICU project. You will find these to be fully portable, and they have full and correct time zone support.
It's worth mentioning that ICU is used in many popular applications. For example, the Google Chrome web browser gets it's time zone support from ICU.
In ICU, the current local system time zone is available as the default time zone. You can read more in the section "Factory Methods and the Default Timezone" in the ICU documentation.
You could always try getting the universal time and local time from boost and checking the difference, it's probably full of caveats though.