I'm trying to implement a function such that can convert a given timezone name string, which it does:
Accepts an input timezone string, for example, "Australia/Melbourne";
Checks host OS (assume it's a POSIX environment) timezone database;
Returns an integer of timezone offset in seconds (for Melbourne in DST, it's 36000).
It can be done by calling putenv("TZ=Australia/Melbourne") but this is may not be thread-safe.
Is there a way to do it without putenv() or somehow let it be thread-safe? Thanks in advance!
Since compilers don't yet support all the features of the C++20 std::chrono library, I will write a solution that's using Howard Hinnant's datehttps://github.com/HowardHinnant/date library. C++20 is introducing std::chrono::zoned_time which you can use to achieve what you want.
#include "date/tz.h"
#include <iostream>
int main()
{
auto current_time = std::chrono::system_clock::now();
auto la = date::zoned_time{"America/Los_Angeles", current_time};
auto sy = date::zoned_time{"Australia/Sydney", current_time};
std::cout << date::format("%T\n", sy.get_local_time() - la.get_local_time());
}
The above example will give you the difference between two time zones. Furthermore, if you want to obtain the current OS's time zone you could use something that, I hope, will be supported by compilers in future - std::chrono::time_zone::name.
In C++20, you will be able to use std::chrono::tzdb::locate_zone(), that will convert a given timezone name to a std::chrono::time_zone object that you can query to get the offset.
There is no standard C function that deals with time zones. There are POSIX.1-compliant functions, but they are indeed not thread-safe. However, depending on your operating system, you might be able to open the timezone database files and parse them manually. For example, on Linux you could open /usr/share/zoneinfo/Australia/Melbourne and parse it according to its specification in the tzfile(5) manpage.
In addition to OP's thread concerns, another consideration:
"timezone offset from timezone name string" is not sufficient in general as the offset differs depending on data/time throughout the year.
Even if no annual daylight adjustments occur in the select zone, the offset can vary due to the history of the zone.
long offset(tz_name) is not enough, long offset(tz_name, time_t t) is needed.
I get a timestamp from a GPS device in a gps_data struct as a double.
I'd like to convert this GPS timestamp to UTC and TAI times, something simple as:
void handle_gps_timestamp(double timestamp)
{
double utc = utc_from_gps(timestamp);
double tai = tai_from_gps(timestamp);
do_stuff(gps, utc, tai);
}
Luckily I found Howard Hinnant's date and timezone library (proposed for C++20) that seems to provide this exact functionality. Unfortunately, at least from what I can see, the date/tz/chrono library has no convenient methods that allow this simple usage.
I must first somehow "transfer" my double into a known chrono/date type. But OK, since I understand the overall concept, namely that the timepoint is defined as a duration after (or before) the epoch of a clock, and I think that this is a beautiful model.
Assumption
I should be able to very easily translate that model to fit my problem, right?
In my case, I have a timestamp that is a point in time, specified as the duration since the gps epoch. Now, there should be a class type of a clock that abstracts and handles all of this for me, I'd like to think. And yes! There is a date::gps_clock and a date::gps_time, which surely should do the work.
Problem
I cannot make it work for me. I'm sure the solution is trivial.
Question
Can someone give me a helping hand, showing how I should use Howard's date library applied to my problem?
It is difficult to answer this question precisely because the input to the problem is underspecified:
I get a timestamp from a GPS device in a gps_data struct as a double ... specified as the duration since the gps epoch.
Therefore I'm going to make some assumptions. I'll state all of my assumptions, and hopefully it will be clear how to alter my answer for other guesses/facts about what that double represents.
Let's say that the double is a non-integral count of milliseconds since the gps epoch. Let's furthermore assume that I want to capture the precision of this input down to microseconds.
#include "date/tz.h"
#include <cstdint>
#include <iostream>
int
main()
{
double gps_input = 1e+12 + 1e-3;
using namespace date;
using namespace std::chrono;
using dms = duration<double, std::milli>;
gps_time<microseconds> gt{round<microseconds>(dms{gps_input})};
auto utc = clock_cast<utc_clock>(gt);
auto tai = clock_cast<tai_clock>(gt);
std::cout << gt << " GPS\n";
std::cout << utc << " UTC\n";
std::cout << tai << " TAI\n";
}
I've arbitrarily created an example input and stored it in gps_input.
Some using directives make the code a lot less verbose.
A custom chrono::duration type that exactly matches the documented specification for what the double represents makes things much simpler, and lessens the chance for errors. In this case I've made a chrono::duration that stores milliseconds in a double and named that type dms.
Now you simply convert the double to dms, and then using round, convert the dms to microseconds, and store those microseconds in a gps time point with precision microseconds or finer. One could use duration_cast in place of round, but when converting from floating point to integral, I usually prefer round, which means round-to-nearest-and-to-even-on-tie.
Now that you have a gps_time, one can use the clock_cast function to convert to other times such as utc_time and tai_time.
This program outputs:
2011-09-14 01:46:40.000001 GPS
2011-09-14 01:46:25.000001 UTC
2011-09-14 01:46:59.000001 TAI
Adjust the milliseconds and microseconds units above as needed. For example if the input represents seconds, the easiest thing to do is to default the second template argument on dms:
using dms = duration<double>;
This library works with C++11/14/17. And with minor modifications it is now part of the official C++20 specification.
The other answer isn't bad but it does require you to have c++17, curl, run cmake, and acquire some custom libraries.
Something that is much easier to drop in as a .h and .cpp would be http://www.leapsecond.com/tools/gpsdate.c.
That doesn't handle the TAI conversion but that might also be on that list.
We have a bespoke datetime C++ class which represents time in number of seconds passed since epoch. This is stored as int64. This class provides number of helper functions to read and write various types of datetime formats.
Unfortunately it cant handle dates before epoch because its methods rely on gmtime() and mktime() for many operations, which on our windows system does not support dates before epoch. Does anyone knows of replacement of gmtime and mktime which support negative values on windows.
An example of this limitation is our applicatio's inability to store birthdays before 1970, that is because every date has to use this class.
I amy not be clear on what I am asking, this is because of my limited knowledge of datetime implementation/use and my reluctance to understand that huge legacy class, so if you feel this question can be framed in another way or I might look for something different feel free to suggest.
You could use Boost.DateTime, or use the Win32 APIs directly rather than the CRT.
It's likely that you have a lot of testing ahead of you to ensure that handling of data does not change in your rework. Make sure you have exhaustive unit tests in place for the library as it stands before you begin any refactoring.
If you have to consider your values being valid across multiple different locations in the world, use UTC time as your canonical form and translate to/from local time as needed for sensible input/display.
Maybe you've solved this problem already since it was years ago, but you could also use ICU. Examples at: http://userguide.icu-project.org/datetime/calendar/examples
Coming soon to a std::lib implementation near you:
#include <chrono>
#include <iostream>
int
main()
{
using namespace std::chrono;
std::cout << "Valid range is ["
<< sys_days{year::min()/January/1} + 0us << ", "
<< sys_days{year::max()/December/31} + 23h + 59min + 59s + 999'999us
<< "]\n";
}
Output:
Valid range is [-32767-01-01 00:00:00.000000, 32767-12-31 23:59:59.999999]
Preview available here.
I am developing an Appointment application in C++ and want to use some Date and Time features.
Is it easier to just use strings when talking about Date and Time, or should I write or get a Date/Time class?
I am wanting to code an appointment class that holds both the time and date of an appointment. Once I have coded the class file, I am wanting to integrate it into a forms application in C++ builder.
I see that there is a TMonthCalendar control. I would like to use this control when making the forms application. As such, what format for the date does this control use? I would like to use the same type as the control when making the class so that I can easily integrate it together.
UPDATE
I have found that it uses the TDateTime type. My question is this: What include statement do I need to use to use this in a console application?
C++11 includes convenience data types and functions for date/time representations, as well as their conversion to strings.
With that, you can do things like this (pretty self-explanatory, I think):
#include <iostream>
#include <iomanip>
#include <ctime>
int main()
{
std::time_t t = std::time(NULL);
std::tm tm = *std::localtime(&t);
std::cout << "Time right now is " << std::put_time(&tm, "%c %Z") << '\n';
}
In particular, there are data types std::time_t and std::tm, and a very nice IO manipulator std::put_time for pretty printing. The format strings used by it are well-documented at cppreference.
This is also supposed to work together well with locales, e.g. for a Japanese time/date format:
std::cout.imbue(std::locale("ja_JP.utf8"));
std::cout << "ja_JP: " << std::put_time(&tm, "%c %Z") << '\n';
The chrono library included in the C++11 standard library also allows you to do simple time/date arithmetic conveniently:
std::chrono::time_point<std::chrono::system_clock> now;
now = std::chrono::system_clock::now();
/* The day before today: */
std::time_t now_c = std::chrono::system_clock::to_time_t(
now - std::chrono::hours(24));
Unfortunately, not all of this is available in all compilers yet. In particular, the std::put_time function does not seem to be available in GCC 4.7.1 yet. To get the code I gave initially to work, I had to use the slightly less elegant std::strftime function:
#include <iostream>
#include <iomanip>
#include <ctime>
int main()
{
std::time_t t = std::time(NULL);
std::tm tm = *std::localtime(&t);
constexpr int bufsize = 100;
char buf[bufsize];
if (std::strftime(buf,bufsize,"%c %Z",&tm) != 0)
std::cout << "Time right now is " << buf << std::endl;
}
Is it easier to just use strings when talking about Date and Time?
No. Even simple things like calculating a duration if you have a meeting start and end date need to account for complex things such as leap years.
should I write or get a Date/Time class?
No. Writing a Date/Time Library seems simple, but it's rather difficult to get right and extremely easy to get wrong. Also, others have done it before - boost is a collection of free libraries with stellar reputation. So many others in fact, that it's become a cliche that newbie programmers want to write a Date/Time library, failing horribly at it.
I see that there is a TMonthCalendar control. [...] I have found that it uses the TDateTime type.
Relying on the same Date/Time class as your GUI framework is ok, but if you later change the GUI framework it can become an issue. Since it's not terribly hard to swap a sensible Date/Time library for another sensible Date/Time library later on, just use one that you find easy to use.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
In new C++ code, I tend to use the C++ iostream library instead of the C stdio library.
I've noticed some programmers seem to stick to stdio, insisting that it's more portable.
Is this really the case? What is better to use?
To answer the original question:
Anything that can be done using stdio can be done using the iostream library.
Disadvantages of iostreams: verbose
Advantages of iostreams: easy to extend for new non POD types.
The step forward the C++ made over C was type safety.
iostreams was designed to be explicitly type safe. Thus assignment to an object explicitly checked the type (at compiler time) of the object being assigned too (generating an compile time error if required). Thus prevent run-time memory over-runs or writing a float value to a char object etc.
scanf()/printf() and family on the other hand rely on the programmer getting the format string correct and there was no type checking (I believe gcc has an extension that helps). As a result it was the source of many bugs (as programmers are less perfect in their analysis than compilers [not going to say compilers are perfect just better than humans]).
Just to clarify comments from Colin Jensen.
The iostream libraries have been stable since the release of the last standard (I forget the actual year but about 10 years ago).
To clarify comments by Mikael Jansson.
The other languages that he mentions that use the format style have explicit safeguards to prevent the dangerous side effects of the C stdio library that can (in C but not the mentioned languages) cause a run-time crash.
N.B. I agree that the iostream library is a bit on the verbose side. But I am willing to put up with the verboseness to ensure runtime safety. But we can mitigate the verbosity by using Boost Format Library.
#include <iostream>
#include <iomanip>
#include <boost/format.hpp>
struct X
{ // this structure reverse engineered from
// example provided by 'Mikael Jansson' in order to make this a running example
char* name;
double mean;
int sample_count;
};
int main()
{
X stats[] = {{"Plop",5.6,2}};
// nonsense output, just to exemplify
// stdio version
fprintf(stderr, "at %p/%s: mean value %.3f of %4d samples\n",
stats, stats->name, stats->mean, stats->sample_count);
// iostream
std::cerr << "at " << (void*)stats << "/" << stats->name
<< ": mean value " << std::fixed << std::setprecision(3) << stats->mean
<< " of " << std::setw(4) << std::setfill(' ') << stats->sample_count
<< " samples\n";
// iostream with boost::format
std::cerr << boost::format("at %p/%s: mean value %.3f of %4d samples\n")
% stats % stats->name % stats->mean % stats->sample_count;
}
It's just too verbose.
Ponder the iostream construct for doing the following (similarly for scanf):
// nonsense output, just to examplify
fprintf(stderr, "at %p/%s: mean value %.3f of %4d samples\n",
stats, stats->name, stats->mean, stats->sample_count);
That would requires something like:
std::cerr << "at " << static_cast<void*>(stats) << "/" << stats->name
<< ": mean value " << std::precision(3) << stats->mean
<< " of " << std::width(4) << std::fill(' ') << stats->sample_count
<< " samples " << std::endl;
String formatting is a case where object-orientedness can, and should be, sidestepped in favour of a formatting DSL embedded in strings. Consider Lisp's format, Python's printf-style formatting, or PHP, Bash, Perl, Ruby and their string intrapolation.
iostream for that use case is misguided, at best.
The Boost Format Library provides a type-safe, object-oriented alternative for printf-style string formatting and is a complement to iostreams that does not suffer from the usual verbosity issues due to the clever use of operator%. I recommend considering it over using plain C printf if you dislike formatting with iostream's operator<<.
Back in the bad old days, the C++ Standards committee kept mucking about with the language and iostreams was a moving target. If you used iostreams, you were then given the opportunity to rewrite parts of your code every year or so. Because of this, I always used stdio which hasn't changed significantly since 1989.
If I were doing stuff today, I would use iostreams.
If, like me, you learned C before learning C++, the stdio libraries seem more natural to use. There are pros and cons for iostream vs. stdio but I do miss printf() when using iostream.
In principle I would use iostreams, in practice I do too much formatted decimals, etc that make iostreams too unreadable, so I use stdio. Boost::format is an improvement, but not quite motivating enough for me. In practice, stdio is nearly typesafe since most modern compilers do argument checking anyway.
It's an area where I'm still not totally happy with any of the solutions.
I'll be comparing the two mainstream libraries from the C++ standard library.
You shouldn't use C-style-format-string-based string-processing-routines in C++.
Several reasons exist to mit their use:
Not typesafe
You can't pass non-POD types to variadic argument lists (i.e., neither to scanf+co., nor to printf+co.),
or you enter the Dark Stronghold of Undefined Behaviour
Easy to get wrong:
You must manage to keep the format string and the "value-argument-list" in sync
You must keep in sync correctly
Subtle bugs introduced at remote places
It is not only the printf in itself that is not good. Software gets old and is refactored and modified, and errors might be introduced from remote places. Suppose you have
.
// foo.h
...
float foo;
...
and somewhere ...
// bar/frob/42/icetea.cpp
...
scanf ("%f", &foo);
...
And three years later you find that foo should be of some custom type ...
// foo.h
...
FixedPoint foo;
...
but somewhere ...
// bar/frob/42/icetea.cpp
...
scanf ("%f", &foo);
...
... then your old printf/scanf will still compile, except that you now get random segfaults and you don't remember why.
Verbosity of iostreams
If you think printf() is less verbose, then there's a certain probability that you don't use their iostream's full force. Example:
printf ("My Matrix: %f %f %f %f\n"
" %f %f %f %f\n"
" %f %f %f %f\n"
" %f %f %f %f\n",
mat(0,0), mat(0,1), mat(0,2), mat(0,3),
mat(1,0), mat(1,1), mat(1,2), mat(1,3),
mat(2,0), mat(2,1), mat(2,2), mat(2,3),
mat(3,0), mat(3,1), mat(3,2), mat(3,3));
Compare that to using iostreams right:
cout << mat << '\n';
You have to define a proper overload for operator<< which has roughly the structure of the printf-thingy, but the significant difference is that you now have something re-usable and typesafe; of course you can also make something re-usable for printf-likes, but then you have printf again (what if you replace the matrix members with the new FixedPoint?), apart from other non-trivialities, e.g. you must pass FILE* handles around.
C-style format strings are not better for I18N than iostreams
Note that format-strings are often thought of being the rescue with internationalization, but they are not at all better than iostream in that respect:
printf ("Guten Morgen, Sie sind %f Meter groß und haben %d Kinder",
someFloat, someInt);
printf ("Good morning, you have %d children and your height is %f meters",
someFloat, someInt); // Note: Position changed.
// ^^ not the best example, but different languages have generally different
// order of "variables"
I.e., old style C format strings lack positional information as much as iostreams do.
You might want to consider boost::format, which offers support for stating the position in the format string explicitly. From their examples section:
cout << format("%1% %2% %3% %2% %1% \n") % "11" % "22" % "333"; // 'simple' style.
Some printf-implementations provide positional arguments, but they are non-standard.
Should I never use C-style format strings?
Apart from performance (as pointed out by Jan Hudec), I don't see a reason. But keep in mind:
“We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. A good programmer will not be lulled into complacency by such reasoning, he will be wise to look carefully at the critical code; but only after that code has been identified” - Knuth
and
“Bottlenecks occur in surprising places, so don't try to second guess and put in a speed hack until you have proven that's where the bottleneck is.” - Pike
Yes, printf-implementations are usually faster than iostreams are usually faster than boost::format (from a small and specific benchmark I wrote, but it should largely depend on the situation in particular: if printf=100%, then iostream=160%, and boost::format=220%)
But do not blindly omit thinking about it: How much time do you really spend on text-processing? How long does your program run before exiting?
Is it relevant at all to fall back to C-style format strings, loose type safety, decrease refactorbility,
increase probability of very subtle bugs that may hide themselves for years and may only reveal themselves right
into your favourites customers face?
Personally, I wouldn't fall back if I can not gain more than 20% speedup. But because my applications
spend virtually all of their time on other tasks than string-processing, I never had to. Some parsers
I wrote spend virtually all their time on string processing, but their total runtime is so small
that it isn't worth the testing and verification effort.
Some riddles
Finally, I'd like to preset some riddles:
Find all errors, because the compiler won't (he can only suggest if he's nice):
shared_ptr<float> f(new float);
fscanf (stdout, "%u %s %f", f)
If nothing else, what's wrong with this one?
const char *output = "in total, the thing is 50%"
"feature complete";
printf (output);
For binary IO, I tend to use stdio's fread and fwrite. For formatted stuff I'll usually use IO Stream although as Mikael said, non-trival (non-default?) formatting can be a PITA.
While there are a lot of benefits to the C++ iostreams API, one significant problem is has is around i18n. The problem is that the order of parameter substitutions can vary based on the culture. The classic example is something like:
// i18n UNSAFE
std::cout << "Dear " << name.given << ' ' << name.family << std::endl;
While that works for English, in Chinese the family name is comes first.
When it comes to translating your code for foreign markets, translating snippets is fraught with peril so new l10ns may require changes to the code and not just different strings.
boost::format seems to combine the best of stdio (a single format string that can use the parameters in a different order then they appear) and iostreams (type-safety, extensibility).
I use iostreams, mainly because that makes it easier to fiddle with the stream later on (if I need it). For example, you could find out that you want to display the output in some trace window -- this is relatively easy to do with cout and cerr. You can, off course, fiddle with pipes and stuff on unix, but that is not as portable.
I do love printf-like formatting, so I usually format a string first, and then send it to the buffer. With Qt, I often use QString::sprintf (although they recommend using QString::arg instead). I've looked at boost.format as well, but couldn't really get used to the syntax (too many %'s). I should really give it a look, though.
What I miss about the iolibraries is the formatted input.
iostreams does not have a nice way to replicate scanf() and even boost does not have the required extension for input.
stdio is better for reading binary files (like freading blocks into a vector<unsigned char> and using .resize() etc.). See the read_rest function in file.hh in http://nuwen.net/libnuwen.html for an example.
C++ streams can choke on lots of bytes when reading binary files causing a false eof.
Since iostreams have become a standard you should use them knowing that your code will work for sure with newer versions of compiler. I guess nowadays most of the compilers know very well about iostreams and there shouldn't be any problem using them.
But if you want to stick with *printf functions there can be no problem in my opinion.