[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

ctime library - is there anything better in c++?

Lars Uffmann

11/20/2008 12:11:00 PM

Is the ctime library really that poorly designed, or is it just me
looking to do things the wrong way?

The whole concept of the struct tm seems way too highlevel for my taste
- this is something that I would implement myself if needed.

I have started programming c++ long before I did Visual Basic, and even
before Visual Basic was around. However, one has to give credit, where
credit is due: What's wrong with the (imo really good) VB approach to
store dates as a floating point value with the whole numbers being the
days since day X and the fraction being the part of the day elapsed?
I.e. 0.5 = 12:00 hours, 1/24 = 1 hour and so on?

If I need any more accurate times, I'll use the timer that starts when
the computer is turned on, not the system clock!

Then the tm structs definitions:
http://www.cplusplus.com/reference/clibrary/cti...
All the values are seconds, minutes, hours, days, months *SINCE* some
point in time, starting with 0, but the tm_mday all of a sudden is "day
of the month" (values 1-31). What ever happened to consistency?

Now if I want to do such a simple thing as read a users text input of a
year and a "day of year", and convert it to an ISO date, I
first: have to create & initialize a tm struct with the date tm_year =
userInput, tm_month = 0, tm_mday = 1, then
second: have to convert that into a time_t value, using mktime()
function that also manipulates my input(!) value,
third: add the user entered "day of year" (minus one) to the time_t,
multiplied by 86400 seconds in a day of course, and finally
fourth: convert the time_t back to a tm struct so I am able to output it
for the user

Not to mention that the tm struct should be a class and initialize in
the constructor with the calendar's counting start date, instead of all
random values (or at least, if it isn't done for speed reasons, an
initialize routine should be part of the library - it's a one-liner, but
it's annoying to do it yourself as a user and include a function that
should be part of the library in every single program that needs it).

Then why on earth does the strftime function take a struct tm as an
argument, and not the (much more sensible) time_t format?

In my eyes, the ctime library is really the poorest piece of programming
I have ever seen in an official c standard library. The only reason I'm
forced to use it at the moment is that I do not know how to reliably
calculate leap years, leap seconds and the likes and really do not feel
like creating my own date/time library at all. Not to mention If I did
it, it wouldn't be anywhere near the speed performance that the standard
library probably is.

So - after being done with my rant, can someone point me to a better
solution in C++?

Best Regards,

Lars

PS: What were they thinking???
16 Answers

mail.dsp

11/20/2008 12:17:00 PM

0

On Nov 20, 5:11 pm, Lars Uffmann <a...@nurfuerspam.de> wrote:
> Is the ctime library really that poorly designed, or is it just me
> looking to do things the wrong way?
>
> The whole concept of the struct tm seems way too highlevel for my taste
> - this is something that I would implement myself if needed.
>
> I have started programming c++ long before I did Visual Basic, and even
> before Visual Basic was around. However, one has to give credit, where
> credit is due: What's wrong with the (imo really good) VB approach to
> store dates as a floating point value with the whole numbers being the
> days since day X and the fraction being the part of the day elapsed?
> I.e. 0.5 = 12:00 hours, 1/24 = 1 hour and so on?
>
> If I need any more accurate times, I'll use the timer that starts when
> the computer is turned on, not the system clock!
>
> Then the tm structs definitions:http://www.cplusplus.com/reference/clibrary/cti...
> All the values are seconds, minutes, hours, days, months *SINCE* some
> point in time, starting with 0, but the tm_mday all of a sudden is "day
> of the month" (values 1-31). What ever happened to consistency?
>
> Now if I want to do such a simple thing as read a users text input of a
> year and a "day of year", and convert it to an ISO date, I
> first: have to create & initialize a tm struct with the date tm_year =
> userInput, tm_month = 0, tm_mday = 1, then
> second: have to convert that into a time_t value, using mktime()
> function that also manipulates my input(!) value,
> third: add the user entered "day of year" (minus one) to the time_t,
> multiplied by 86400 seconds in a day of course, and finally
> fourth: convert the time_t back to a tm struct so I am able to output it
> for the user
>
> Not to mention that the tm struct should be a class and initialize in
> the constructor with the calendar's counting start date, instead of all
> random values (or at least, if it isn't done for speed reasons, an
> initialize routine should be part of the library - it's a one-liner, but
> it's annoying to do it yourself as a user and include a function that
> should be part of the library in every single program that needs it).
>
> Then why on earth does the strftime function take a struct tm as an
> argument, and not the (much more sensible) time_t format?
>
> In my eyes, the ctime library is really the poorest piece of programming
> I have ever seen in an official c standard library. The only reason I'm
> forced to use it at the moment is that I do not know how to reliably
> calculate leap years, leap seconds and the likes and really do not feel
> like creating my own date/time library at all. Not to mention If I did
> it, it wouldn't be anywhere near the speed performance that the standard
> library probably is.
>
> So - after being done with my rant, can someone point me to a better
> solution in C++?
>
> Best Regards,
>
> Lars
>
> PS: What were they thinking???

Use boost library. It is open source. Download it from
www.boost.org

--
Daya

Lars Uffmann

11/20/2008 12:18:00 PM

0

mail.dsp@gmail.com wrote:
> Use boost library. It is open source. Download it from
> www.boost.org

oO! That was too obvious :/ Thank you! I already use boost for
threading, so I don't even have to download it.

Thanks for the fast reply!

Lars

Juha Nieminen

11/20/2008 1:12:00 PM

0

Lars Uffmann wrote:
> What's wrong with the (imo really good) VB approach to
> store dates as a floating point value with the whole numbers being the
> days since day X and the fraction being the part of the day elapsed?

Accuracy comes to mind. For example the value 0.1 cannot be
represented accurately with base-2 floating point numbers (for the exact
same reason as 1/3 cannot be represented accurately with base-10 decimal
numbers).

If you add 0.1 to itself 10 times, you won't get 1.0 (you get a value
which is extremely close to it, but not exactly 1.0). That might not be
what one wants.

ytrembla

11/20/2008 3:39:00 PM

0

In article <6ol2erF462vhU1@mid.dfncis.de>,
Lars Uffmann <aral@nurfuerspam.de> wrote:
>Is the ctime library really that poorly designed, or is it just me
>looking to do things the wrong way?
>
>The whole concept of the struct tm seems way too highlevel for my taste
>- this is something that I would implement myself if needed.
>
>I have started programming c++ long before I did Visual Basic, and even
>before Visual Basic was around. However, one has to give credit, where
>credit is due: What's wrong with the (imo really good) VB approach to
>store dates as a floating point value with the whole numbers being the
>days since day X and the fraction being the part of the day elapsed?
>I.e. 0.5 = 12:00 hours, 1/24 = 1 hour and so on?

Sounds poor to me...

>If I need any more accurate times, I'll use the timer that starts when
>the computer is turned on, not the system clock!
>
>Then the tm structs definitions:
>http://www.cplusplus.com/reference/clibrary/cti...
>All the values are seconds, minutes, hours, days, months *SINCE* some
>point in time, starting with 0, but the tm_mday all of a sudden is "day
>of the month" (values 1-31). What ever happened to consistency?

Euh, ask the peoples that invented the time system. In most cultures
I have been exposed to, a day starts at 00:00:00 as hours, minutes
and seconds (some use 12:00:00 AM but most understand both). Nowhere
that I am aware start their day at 01:01:01.

Inconsistently, most culture start their years on the 01/01 i.e first
day of the first month. Nowhere that I am aware of start their years
on 00/00.

So the C library when creating a human referenceable structure simply
followed accepted human patterns.

>Now if I want to do such a simple thing as read a users text input of a
>year and a "day of year", and convert it to an ISO date, I
>first: have to create & initialize a tm struct with the date tm_year =
>userInput, tm_month = 0, tm_mday = 1, then
>second: have to convert that into a time_t value, using mktime()
>function that also manipulates my input(!) value,
>third: add the user entered "day of year" (minus one) to the time_t,
>multiplied by 86400 seconds in a day of course, and finally
>fourth: convert the time_t back to a tm struct so I am able to output it
>for the user

Sounds convoluted to me. Don't you have strptime?
http://www.opengroup.org/onlinepubs/009695399/functions/str...

strptime allows you to do things like:
strptime("6 Dec 2001 12:33:45", "%d %b %Y %H:%M:%S", &tm)

Seems fairly usable. That should do what you want.

Yannick

Lars Uffmann

11/20/2008 3:57:00 PM

0

Juha Nieminen wrote:
>> What's wrong with the (imo really good) VB approach to
>> store dates as a floating point value with the whole numbers being the
>> days since day X and the fraction being the part of the day elapsed?
>
> Accuracy comes to mind. For example the value 0.1 cannot be
> represented accurately with base-2 floating point numbers (for the exact
> same reason as 1/3 cannot be represented accurately with base-10 decimal
> numbers).

Okay, that is a valid point. However, the same point holds true for the
time_t format - just at a higher level of details, with exactly the
examle of 1/3 that you mentioned. :)

Best Regards,

Lars

Lars Uffmann

11/20/2008 4:04:00 PM

0

Yannick Tremblay wrote:
>> I.e. 0.5 = 12:00 hours, 1/24 = 1 hour and so on?
> Sounds poor to me...

YMMD - it makes for very easy date calculation when you have to handle
lots and lots of date routines (where speed isn't as big an issue as
variety).

>> All the values are seconds, minutes, hours, days, months *SINCE* some
>> point in time, starting with 0, but the tm_mday all of a sudden is "day
>> of the month" (values 1-31). What ever happened to consistency?
>
> Euh, ask the peoples that invented the time system. In most cultures
> I have been exposed to, a day starts at 00:00:00 as hours, minutes
> and seconds (some use 12:00:00 AM but most understand both). Nowhere
> that I am aware start their day at 01:01:01.

Well - then why is the ctime implementation of struct tm also counting
months starting from zero? And the weekday (tm_wday), day of year
(tm_yday) as well as the year (ok, actually that is being counted from
1970 - also a big limitation of this time format: due to the
unnecessarily high accuracy, you can not express any dates prior to
1902-01-01...

> So the C library when creating a human referenceable structure simply
> followed accepted human patterns.
Not really ;)

> Sounds convoluted to me. Don't you have strptime?
> http://www.opengroup.org/onlinepubs/009695399/functions/str...
No, I was not aware of it, but that was the purpose of my OP - I wanted
to learn about alternatives :) So thanks for that!

Best Regards,

Lars

James Kanze

11/21/2008 9:36:00 AM

0

On Nov 20, 2:12 pm, Juha Nieminen <nos...@thanks.invalid> wrote:
> Lars Uffmann wrote:
> > What's wrong with the (imo really good) VB approach to store
> > dates as a floating point value with the whole numbers being
> > the days since day X and the fraction being the part of the
> > day elapsed?

> Accuracy comes to mind. For example the value 0.1 cannot be
> represented accurately with base-2 floating point numbers (for
> the exact same reason as 1/3 cannot be represented accurately
> with base-10 decimal numbers).

> If you add 0.1 to itself 10 times, you won't get 1.0 (you get
> a value which is extremely close to it, but not exactly 1.0).
> That might not be what one wants.

Just a nit, but you *might* get 1.0. More accurately, too, you
probably can't add 0.1 to itself, because you can't have a value
0.1, just a value which is extremely close to it. Although the
standard allows base 10 floating pointer arithmetic, I don't
know of a modern implementation that uses anything other than
base 2, 8 or 16. And 0.1 isn't representable in any of those
bases. (And of course, if adding 0.1 ten times does happen to
work, just choose some other value---whatever the
representation, adding 1/N to itself N times will fail to give 1
for some N. Because 1/N isn't representable.)

But the basic objection remains: you can't exactly represent
seconds, and the results of any calculations which should result
in seconds may be off by some very small amount. Which could
cause problems if you want to compare two times. Not to mention
that you're likely to end up with fractions of a second when you
don't want them. All in all, using floating point here is
probably the worst possible solution (but the standard allows
it: time_t may be a typedef to double).

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

James Kanze

11/21/2008 9:51:00 AM

0

On Nov 20, 5:04 pm, Lars Uffmann <a...@nurfuerspam.de> wrote:
> Yannick Tremblay wrote:
> >> I.e. 0.5 = 12:00 hours, 1/24 = 1 hour and so on?
> > Sounds poor to me...

> YMMD - it makes for very easy date calculation when you have
> to handle lots and lots of date routines (where speed isn't as
> big an issue as variety).

> >> All the values are seconds, minutes, hours, days, months
> >> *SINCE* some point in time, starting with 0, but the
> >> tm_mday all of a sudden is "day of the month" (values
> >> 1-31). What ever happened to consistency?

> > Euh, ask the peoples that invented the time system. In most
> > cultures I have been exposed to, a day starts at 00:00:00 as
> > hours, minutes and seconds (some use 12:00:00 AM but most
> > understand both). Nowhere that I am aware start their day
> > at 01:01:01.

> Well - then why is the ctime implementation of struct tm also
> counting months starting from zero? And the weekday (tm_wday),

Because these values are strings; adding numbers to strings
doesn't work very well, but adding a number to the index into a
table of strings does. And in C, indexes start at 0.

> day of year (tm_yday) as well as the year (ok, actually that
> is being counted from 1970

In time_t. In tm, its from 1900. Format the tm_year field as
%02d, and you get a 2 digit year, exactly as people back in the
1970's (when time.h was designed) would expect it.

> - also a big limitation of this time format: due to the
> unnecessarily high accuracy, you can not express any dates
> prior to 1902-01-01...

Again, it's implementation defined. But most implementations do
use the Unix conventions, or something similar (in particular,
with time_t being a 32 bit integer). And again: this format was
designed mainly for file timestamps; the inventors weren't
worried about files which were modified before 1970, since they
couldn't exist.

For a general purpose library, 32 bits aren't enough, even for a
resolution of seconds. (A 64 bit value representing nanoseconds
is good for over 200,000 years, and representing microseconds,
for well over the expected age of the universe. Which should
cover most needs.)

> > So the C library when creating a human referenceable
> > structure simply followed accepted human patterns.

> Not really ;)

Very really, within the context

> > Sounds convoluted to me. Don't you have strptime?
> >http://www.opengroup.org/onlinepubs/009695399/functions/str...

> No, I was not aware of it, but that was the purpose of my OP -
> I wanted to learn about alternatives :) So thanks for that!

Note that it's a Unix standard function, not necessarily
available everywhere.

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

osmium

11/21/2008 5:33:00 PM

0

"Lars Uffmann" wrote:

> Is the ctime library really that poorly designed, or is it just me looking
> to do things the wrong way?

I haven't followed this thread but the linked article is germane to the
general discussion. It says 28 GIs were killed because of
rounding/truncation/whatever error. It took me till now to get around to
looking for a clip of some kind, I had heard about the problem quite some
time ago.

http://www.ima.umn.edu/~arnold/disasters/pa...


Lars Uffmann

11/24/2008 10:56:00 AM

0

James Kanze wrote:
>> day of year (tm_yday) as well as the year (ok, actually that
>> is being counted from 1970
>
> In time_t. In tm, its from 1900.

Ouch! So that is where that inconsistency comes from. I've been wondrin
why in my conversion routine, the date would sometimes be 1970-01-01
when I try to convert a date lower than the minimum tm value to a time_t.
By the way, the minimum for tm seems to be 1902-01-01 - though I'd have
to do some debugging on my code to be sure the observed behaviour of my
mini-program is indeed the behaviour of the underlying conversion
functions of ctime.


> with time_t being a 32 bit integer). And again: this format was
> designed mainly for file timestamps; the inventors weren't
> worried about files which were modified before 1970, since they
> couldn't exist.
Oh - okay, that makes a little more sense. I thought it was meant for
calendar calculations and the likes...

> For a general purpose library, 32 bits aren't enough, even for a
> resolution of seconds. (A 64 bit value representing nanoseconds
> is good for over 200,000 years, and representing microseconds,
> for well over the expected age of the universe. Which should
> cover most needs.)
I'm not so sure... What about the next universe? And the one after that?
Suppose I want to write a letter to my 10^913th generation son? :D


> Note that it's a Unix standard function, not necessarily
> available everywhere.
K, all the same to someone developing with MinGW ;)

Thanks again!

Lars