Converting date string to a number

J

Jef Driesen

How can I convert a date string to a number (e.g. a time_t value or a tm
struct)? I know about the strptime function, but then I have to know the
format string. And that is a problem.

I'm trying to autoformat the contents of text entries in a GUI. For
numbers, I'm converting the text representation to the appropriate type
(using atoi, atof, ...) and converting the result back to text with the
correct format (using sprintf). But this does not work for date (or
time) strings.

For instance, if the desired date format is "dd-mm-yy", but the user
enters "dd-mm-yyyy", I can't convert the string to a valid date, because
I don't know its format.
 
J

Jim Langston

Jef Driesen said:
How can I convert a date string to a number (e.g. a time_t value or a tm
struct)? I know about the strptime function, but then I have to know the
format string. And that is a problem.

I'm trying to autoformat the contents of text entries in a GUI. For
numbers, I'm converting the text representation to the appropriate type
(using atoi, atof, ...) and converting the result back to text with the
correct format (using sprintf). But this does not work for date (or time)
strings.

For instance, if the desired date format is "dd-mm-yy", but the user
enters "dd-mm-yyyy", I can't convert the string to a valid date, because I
don't know its format.

atoi, atof, etc.. are a pain in the neck. If you use stringstream it's
rather easy.

std::cout << "Enter Date:";
std::cin >> Date;
std::stringstream Stream(Date);
int Month, Day, Year;
char Hyphen;

if ( Stream >> Month >> Hyphen >> Day >> Hyphen >> Year )
// Got good date. Values in Month, Day and year. Should validate them
somehow
else
// Something went wrong, not in right format.

The good thing about this is, you don't have to care how long the month, day
or year entries are. They could enter a 1 or 100 digit number, and it would
read it. Of course, after this is done you want to do reality checking.
I.E. Is month 1-12? Is day 1-31? If year is 2 digit, do you want to add
1900 or 2000? If year is 4 digit, is it realistic? Etc...
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

How can I convert a date string to a number (e.g. a time_t value or a tm
struct)? I know about the strptime function, but then I have to know the
format string. And that is a problem.

I'm trying to autoformat the contents of text entries in a GUI. For
numbers, I'm converting the text representation to the appropriate type
(using atoi, atof, ...) and converting the result back to text with the
correct format (using sprintf). But this does not work for date (or
time) strings.

For instance, if the desired date format is "dd-mm-yy", but the user
enters "dd-mm-yyyy", I can't convert the string to a valid date, because
I don't know its format.

Since you are using a GUI framework check if there is some kind of
date/time class/thingie which can parse time and dates. Standard C++ is
quite poorly equipped on this area but most frameworks have better support.
 
J

Jef Driesen

Jim said:
atoi, atof, etc.. are a pain in the neck. If you use stringstream it's
rather easy.

std::cout << "Enter Date:";
std::cin >> Date;
std::stringstream Stream(Date);
int Month, Day, Year;
char Hyphen;

if ( Stream >> Month >> Hyphen >> Day >> Hyphen >> Year )
// Got good date. Values in Month, Day and year. Should validate them
somehow
else
// Something went wrong, not in right format.

The good thing about this is, you don't have to care how long the month, day
or year entries are. They could enter a 1 or 100 digit number, and it would
read it. Of course, after this is done you want to do reality checking.
I.E. Is month 1-12? Is day 1-31? If year is 2 digit, do you want to add
1900 or 2000? If year is 4 digit, is it realistic? Etc...

This approach using stringstream has (almost) the same problem. You
still need to know the order of the 'components'. And that can be
different in another locale:

yyyy-mm-dd (ISO)
dd/mm/yyyy (Europe)
mm/dd/yyyy (US)

I don't need to be able to handle all possible formats, because that is
impossible (e.g. is 01/01/2007 a European or a US style date?). But I do
want to handle some minor variations of the preferred format, like the 2
or 4 digit year, a change in hyphen (- or /) and things like that.
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

This approach using stringstream has (almost) the same problem. You
still need to know the order of the 'components'. And that can be
different in another locale:

yyyy-mm-dd (ISO)
dd/mm/yyyy (Europe)
mm/dd/yyyy (US)

I don't need to be able to handle all possible formats, because that is
impossible (e.g. is 01/01/2007 a European or a US style date?). But I do
want to handle some minor variations of the preferred format, like the 2
or 4 digit year, a change in hyphen (- or /) and things like that.

If you fix the order (ie. must be year, month, day) you should be able
to let the user separate them however he likes, and also use as many
number of digits for each field as he wishes.
 
J

Jef Driesen

Erik said:
Since you are using a GUI framework check if there is some kind of
date/time class/thingie which can parse time and dates. Standard C++ is
quite poorly equipped on this area but most frameworks have better support.

I'm using gtkmm (the C++ bindings for gtk+), but it doesn't seem to have
more advanced date/time functions.
 
J

James Kanze

[...]
If the components are all numeric, you need that anyway. If I
enter 01/02/03: is it 3 Febuary, 2001, 1 Febuary 2003 or 2
January, 2003?

The classical solution to the problem is to display a label
above the text box specifying the format, and then require the
user to conform exactly.
If you fix the order (ie. must be year, month, day) you should be able
to let the user separate them however he likes, and also use as many
number of digits for each field as he wishes.

You can allow some variance in the order if you enter the month
as text, e.g. JAN, FEB...

Otherwise, it's pretty simple to write a manipulator which will
skip any separator from a list of legal separators, and then all
you have to write is:

input >> day >> skipSep( "/-." ) >> month >> skipSep( "/-." ) >>
year ;
 
J

Jef Driesen

James said:
Jim Langston wrote:
in message
[...]

The good thing about this is, you don't have to care how
long the month, day or year entries are. They could enter
a 1 or 100 digit number, and it would read it. Of course,
after this is done you want to do reality checking. I.E.
Is month 1-12? Is day 1-31? If year is 2 digit, do you
want to add 1900 or 2000? If year is 4 digit, is it
realistic? Etc...

This approach using stringstream has (almost) the same problem. You
still need to know the order of the 'components'.

If the components are all numeric, you need that anyway. If I
enter 01/02/03: is it 3 Febuary, 2001, 1 Febuary 2003 or 2
January, 2003?

The classical solution to the problem is to display a label
above the text box specifying the format, and then require the
user to conform exactly.
If you fix the order (ie. must be year, month, day) you should be able
to let the user separate them however he likes, and also use as many
number of digits for each field as he wishes.

You can allow some variance in the order if you enter the month
as text, e.g. JAN, FEB...

Otherwise, it's pretty simple to write a manipulator which will
skip any separator from a list of legal separators, and then all
you have to write is:

input >> day >> skipSep( "/-." ) >> month >> skipSep( "/-." ) >>
year ;

The problem is I don't want to use a fixed date format in my
application, because there is no "best" format for every user. That's
why the format should be obtained from the locale or some preference.
 
J

Jim Langston

Jef Driesen said:
James said:
On 2007-07-18 13:21, Jef Driesen wrote:
Jim Langston wrote:
in message
[...]

The good thing about this is, you don't have to care how
long the month, day or year entries are. They could enter
a 1 or 100 digit number, and it would read it. Of course,
after this is done you want to do reality checking. I.E.
Is month 1-12? Is day 1-31? If year is 2 digit, do you
want to add 1900 or 2000? If year is 4 digit, is it
realistic? Etc...

This approach using stringstream has (almost) the same problem. You
still need to know the order of the 'components'.

If the components are all numeric, you need that anyway. If I
enter 01/02/03: is it 3 Febuary, 2001, 1 Febuary 2003 or 2
January, 2003?

The classical solution to the problem is to display a label
above the text box specifying the format, and then require the
user to conform exactly.
And that can be
different in another locale:

yyyy-mm-dd (ISO)
dd/mm/yyyy (Europe)
mm/dd/yyyy (US)

I don't need to be able to handle all possible formats, because that is
impossible (e.g. is 01/01/2007 a European or a US style date?). But I
do
want to handle some minor variations of the preferred format, like the
2
or 4 digit year, a change in hyphen (- or /) and things like that.

If you fix the order (ie. must be year, month, day) you should be able
to let the user separate them however he likes, and also use as many
number of digits for each field as he wishes.

You can allow some variance in the order if you enter the month
as text, e.g. JAN, FEB...

Otherwise, it's pretty simple to write a manipulator which will
skip any separator from a list of legal separators, and then all
you have to write is:

input >> day >> skipSep( "/-." ) >> month >> skipSep( "/-." ) >>
year ;

The problem is I don't want to use a fixed date format in my application,
because there is no "best" format for every user. That's why the format
should be obtained from the locale or some preference.

If the format is obtained from the locale or some preference, then read you
data using that locate/preference.

It sounds like you want a C++ function that given a date in a std::string
looks at the locale and/or some preference and returns a date value. Well,
it's not built into C++. I don't think it's biult into boost either or
someone would of brought it up by now. So you need to roll your own.

pseudo code:
if ( locate == "USA" )
// read MM/DD/YY
else if ( locoae == "UK" )
// read DD/MM/YY
else if ( locale == "ISO" )
// read YYYY-MM-DD
etc...

anything you download to do this or any function you called would have to do
the exact same thing anyway.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top