473,383 Members | 1,759 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,383 software developers and data experts.

Using time_put and time_get from <locale>.

Dear group,

I have been struggling to get a simple program for inserting and
extracting std::tm objects to/from streams to work. The code below tries
to read a std::tm object from a std::istringstream but fails to do so,
could anybody see what is wrong with the code? (Output follows the code.)
I fear that I have not completely grasped how the time_getXXX methods
should be used in the operator<< ?

With best regards,
Peter Jansson


// ---- CODE BEGIN ---- //
#include <ctime>
#include <iostream>
#include <locale>
#include <sstream>
#include <string>
std::istream& operator>>(std::istream& s,struct std::tm& t);
std::ostream& operator<<(std::ostream& s,const struct std::tm& t);
int main()
{
struct std::tm t={0};
t.tm_year=2006-1900;
t.tm_mon=1-1;
t.tm_mday=14;
t.tm_hour=19;
t.tm_min=22;
t.tm_sec=0;
std::cout<<"Date-time at start: "<<t<<'\n';
std::string dateTimeString("1976-07-02 05:45:03");
std::cout<<"Date-time to read from a stream: "<<dateTimeString<<'\n';
std::istringstream iss(dateTimeString);
iss>>t;
std::cout<<"Date-time after reading from a stream: "<<t<<'\n';
std::cout<<"Should be: 1976-07-02 05:45:03\n";
return 0;
}
std::istream& operator>>(std::istream& s,struct std::tm& t)
{
using namespace std;
istream::sentry cerberos(s);
if(cerberos) {
ios_base::iostate err = ios::goodbit;
typedef istreambuf_iterator<char> ist;
ist from=ist(s),end=ist();
const time_get<char>& tg=use_facet< time_get<char> >(s.getloc());
tg.get_date(from,end,s,err,&t);
tg.get_time(from,end,s,err,&t);
// Or should something like the following 3 lines be used?
//tg.get_year(from,end,s,err,&t);
//tg.get_date(from,end,s,err,&t);
//tg.get_time(from,end,s,err,&t);
s.setstate(err);
}
return s;
}
std::ostream& operator<<(std::ostream& s,const struct std::tm& t)
{
using namespace std;
ostream::sentry cerberos(s);
if(cerberos) {
const char* fmt="%Y-%m-%d %H:%M:%S";
use_facet< time_put<char> >(s.getloc()).put(s,s,s.fill(),&t,fmt,fmt+17);
}
return s;
}
// ---- CODE BEGIN ---- //
// ---- SAMPLE OUTPUT BEGIN ---- //
Date-time at start: 2006-01-14 19:22:00
Date-time to read from a stream: 1976-07-02 05:45:03
Date-time after reading from a stream: 2006-01-14 19:22:00
Should be: 1976-07-02 05:45:03
// ---- SAMPLE OUTPUT END ---- //

Jan 14 '06 #1
7 3477
TB
Peter Jansson sade:
Dear group,

I have been struggling to get a simple program for inserting and
extracting std::tm objects to/from streams to work. The code below tries
to read a std::tm object from a std::istringstream but fails to do so,
could anybody see what is wrong with the code? (Output follows the code.)
I fear that I have not completely grasped how the time_getXXX methods
should be used in the operator<< ?

With best regards,
Peter Jansson


// ---- CODE BEGIN ---- // <snip> std::string dateTimeString("1976-07-02 05:45:03"); <snip> std::istream& operator>>(std::istream& s,struct std::tm& t)
{
using namespace std;
istream::sentry cerberos(s);
if(cerberos) {
ios_base::iostate err = ios::goodbit;
typedef istreambuf_iterator<char> ist;
ist from=ist(s),end=ist();
const time_get<char>& tg=use_facet< time_get<char> >(s.getloc());
tg.get_date(from,end,s,err,&t);
tg.get_time(from,end,s,err,&t);
// Or should something like the following 3 lines be used?
//tg.get_year(from,end,s,err,&t);
//tg.get_date(from,end,s,err,&t);
//tg.get_time(from,end,s,err,&t);
s.setstate(err);
}
return s;
}

<snip>

Maybe I'm not remembering this frameset correctly, but shouldn't
'from' and 'end' isolate the specified range for each parsing.
i.e.
For tg.get_date() 'from' should be index 0, and 'end' should be index 10.
For tg.get_time() 'from' should be index 11 and 'end' should be index 19.
Otherwise the parsing fails and nothing is put in 't'.

TB
Jan 14 '06 #2
TB wrote:
Peter Jansson sade:
Dear group,

I have been struggling to get a simple program for inserting and
extracting std::tm objects to/from streams to work. The code below
tries to read a std::tm object from a std::istringstream but fails to
do so, could anybody see what is wrong with the code? (Output follows
the code.)
I fear that I have not completely grasped how the time_getXXX methods
should be used in the operator<< ?

With best regards,
Peter Jansson


// ---- CODE BEGIN ---- //


<snip>
std::string dateTimeString("1976-07-02 05:45:03");


<snip>
std::istream& operator>>(std::istream& s,struct std::tm& t)
{
using namespace std;
istream::sentry cerberos(s);
if(cerberos) {
ios_base::iostate err = ios::goodbit;
typedef istreambuf_iterator<char> ist;
ist from=ist(s),end=ist();
const time_get<char>& tg=use_facet< time_get<char> >(s.getloc());
tg.get_date(from,end,s,err,&t);
tg.get_time(from,end,s,err,&t);
// Or should something like the following 3 lines be used?
//tg.get_year(from,end,s,err,&t);
//tg.get_date(from,end,s,err,&t);
//tg.get_time(from,end,s,err,&t);
s.setstate(err);
}
return s;
}


<snip>

Maybe I'm not remembering this frameset correctly, but shouldn't
'from' and 'end' isolate the specified range for each parsing.
i.e.
For tg.get_date() 'from' should be index 0, and 'end' should be index 10.
For tg.get_time() 'from' should be index 11 and 'end' should be index 19.
Otherwise the parsing fails and nothing is put in 't'.

TB


Yes, the methods parse the input using the iterators over the range
(from,end] but how can we specify that range using istreambuf_iterator?
tg.get_date(from,from+10,...) obviously does not work since +10 is not
defined...

Regard,
Peter Jansson
Jan 15 '06 #3
TB
Peter Jansson sade:
TB wrote:
Peter Jansson sade:
<snip> <snip>
std::string dateTimeString("1976-07-02 05:45:03");
<snip>
std::istream& operator>>(std::istream& s,struct std::tm& t)
{
using namespace std;
istream::sentry cerberos(s);
if(cerberos) {
ios_base::iostate err = ios::goodbit;
typedef istreambuf_iterator<char> ist;
ist from=ist(s),end=ist();
const time_get<char>& tg=use_facet< time_get<char> >(s.getloc());
tg.get_date(from,end,s,err,&t);
tg.get_time(from,end,s,err,&t);
// Or should something like the following 3 lines be used?
//tg.get_year(from,end,s,err,&t);
//tg.get_date(from,end,s,err,&t);
//tg.get_time(from,end,s,err,&t);
s.setstate(err);
}
return s;
}


<snip>

Maybe I'm not remembering this frameset correctly, but shouldn't
'from' and 'end' isolate the specified range for each parsing.
i.e.
For tg.get_date() 'from' should be index 0, and 'end' should be index 10.
For tg.get_time() 'from' should be index 11 and 'end' should be index 19.
Otherwise the parsing fails and nothing is put in 't'.

TB


Yes, the methods parse the input using the iterators over the range
(from,end] but how can we specify that range using istreambuf_iterator?
tg.get_date(from,from+10,...) obviously does not work since +10 is not
defined...


Here comes a modified version of your code. First you need to find out
in what order dates are represented on your system, easily done with:

int main() {
const std::time_get<char>& tg=std::use_facet< std::time_get<char>(std::cin.getloc());

switch(tg.date_order()) {
case std::time_base::no_order:
std::cout<<"no\n"; break;
case std::time_base::dmy:
std::cout<<"dmy\n"; break;
case std::time_base::mdy:
std::cout<<"mdy\n"; break;
case std::time_base::ymd:
std::cout<<"ymd\n"; break;
case std::time_base::ydm:
std::cout<<"ydm\n"; break;
}
return 0;
}

On my system/loc it's "mdy". Then change your date string accordingly:
std::string dateTimeString("7/2/1976 05:45:03");

And with a few changes, this works for me:

std::istream& operator>>(std::istream& s,struct std::tm& t)
{
using namespace std;
istream::sentry cerberos(s);
if(cerberos) {
ios_base::iostate err = ios::goodbit;
typedef istreambuf_iterator<char> ist;
const time_get<char>& tg=use_facet< time_get<char> >(s.getloc());
ist from(s), end;
tg.get_date(from,end,s,err,&t);
++from;
tg.get_time(from,end,s,err,&t);
s.setstate(err);
}
return s;
}

TB
Jan 15 '06 #4
On Sun, 15 Jan 2006, TB wrote:
Here comes a modified version of your code. First you need to find out
in what order dates are represented on your system, easily done with:

int main() {
const std::time_get<char>& tg=std::use_facet< std::time_get<char>
(std::cin.getloc());

switch(tg.date_order()) {
case std::time_base::no_order:
std::cout<<"no\n"; break;
case std::time_base::dmy:
std::cout<<"dmy\n"; break;
case std::time_base::mdy:
std::cout<<"mdy\n"; break;
case std::time_base::ymd:
std::cout<<"ymd\n"; break;
case std::time_base::ydm:
std::cout<<"ydm\n"; break;
}
return 0;
}

On my system/loc it's "mdy". Then change your date string accordingly:
std::string dateTimeString("7/2/1976 05:45:03");

And with a few changes, this works for me:

std::istream& operator>>(std::istream& s,struct std::tm& t)
{
using namespace std;
istream::sentry cerberos(s);
if(cerberos) {
ios_base::iostate err = ios::goodbit;
typedef istreambuf_iterator<char> ist;
const time_get<char>& tg=use_facet< time_get<char> >(s.getloc());
ist from(s), end;
tg.get_date(from,end,s,err,&t);
++from;
tg.get_time(from,end,s,err,&t);
s.setstate(err);
}
return s;
}

TB


Thank you TB for your answer to my struggle!

I had to modify also the operator<< method to insert the std::tm using the
format the of current locale: 'x' and 'X' and with ++from the code works
fine, again: Thanks! Below is the full code I ended up with.

Best regards,
Peter Jansson
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <locale>
#include <sstream>
#include <string>
std::istream& operator>>(std::istream& s,struct std::tm& t);
std::ostream& operator<<(std::ostream& s,const struct std::tm& t);
int main()
{
std::cout<<"Determining date order: ";
const std::time_get<char>& tg=std::use_facet< std::time_get<char> >(std::cin.getloc());
switch(tg.date_order()) {
case std::time_base::no_order:
std::cout<<"no order"; break;
case std::time_base::dmy:
std::cout<<"dmy"; break;
case std::time_base::mdy:
std::cout<<"mdy"; break;
case std::time_base::ymd:
std::cout<<"ymd"; break;
case std::time_base::ydm:
std::cout<<"ydm"; break;
}
std::cout<<'\n';
struct std::tm t={0};
t.tm_year=2006-1900;
t.tm_mon=1-1;
t.tm_mday=14;
t.tm_hour=19;
t.tm_min=22;
t.tm_sec=0;
std::cout<<"Date-time at start: "<<t<<'\n';
struct std::tm t2={0};
t2.tm_year=1986-1900;
t2.tm_mon=7-1;
t2.tm_mday=2;
t2.tm_hour=5;
t2.tm_min=45;
t2.tm_sec=3;
std::ostringstream t2s; t2s<<t2;
std::string dateTimeString(t2s.str());
std::cout<<"Date-time to read from a stream: "<<dateTimeString<<'\n';
std::istringstream iss(dateTimeString);
iss>>t;
std::cout<<"Date-time after reading from a stream: "<<t<<'\n';
return EXIT_SUCCESS;
}
std::istream& operator>>(std::istream& s,struct std::tm& t)
{
using namespace std;
istream::sentry cerberos(s);
if(cerberos) {
ios_base::iostate err = ios::goodbit;
typedef istreambuf_iterator<char> ist;
ist from(s),end;
const time_get<char>& tg=use_facet< time_get<char> >(s.getloc());
ist last=tg.get_date(from,end,s,err,&t);
++from;
tg.get_time(from,end,s,err,&t);
s.setstate(err);
}
return s;
}
std::ostream& operator<<(std::ostream& s,const struct std::tm& t)
{
using namespace std;
ostream::sentry cerberos(s);
if(cerberos) {
const time_put<char>& tp=use_facet< time_put<char> >(s.getloc());
tp.put(s,s,s.fill(),&t,'x');
s<<s.fill();
tp.put(s,s,s.fill(),&t,'X');
}
return s;
}
Jan 15 '06 #5
TB
Peter Jansson sade:
std::ostream& operator<<(std::ostream& s,const struct std::tm& t)
{
using namespace std;
ostream::sentry cerberos(s);
if(cerberos) {
const time_put<char>& tp=use_facet< time_put<char> >(s.getloc());
tp.put(s,s,s.fill(),&t,'x');
s<<s.fill();
tp.put(s,s,s.fill(),&t,'X');
}
return s;
}
Hm, I accidently ignored that function. No need to bother with
std::time_get<>::date_order() then, the framework does it for you
on a more portable level.
std::ostringstream t2s; t2s<<t2;
std::string dateTimeString(t2s.str());
std::cout<<"Date-time to read from a stream:
"<<dateTimeString<<'\n';
std::istringstream iss(dateTimeString);
iss>>t;


You could alway just do:

std::stringstream sstrm;
sstrm << t2;
std::cout<<sstrm.str();
sstrm >> t;

Lycka Till.

TB
Jan 15 '06 #6
On Sun, 15 Jan 2006, TB wrote:
Hm, I accidently ignored that function. No need to bother with
std::time_get<>::date_order() then, the framework does it for you
on a more portable level.
std::ostringstream t2s; t2s<<t2;
std::string dateTimeString(t2s.str());
std::cout<<"Date-time to read from a stream:
"<<dateTimeString<<'\n';
std::istringstream iss(dateTimeString);
iss>>t;


You could alway just do:

std::stringstream sstrm;
sstrm << t2;
std::cout<<sstrm.str();
sstrm >> t;

Lycka Till.

TB


Hej,

I assume I "could always just do" those last lines if I have defined the
operator<< and operator>> for std::tm?

I also noted that the global locale gets set to the classic "C" locale
upon program startup so I had to set it to the user defined default;
std::locale("") and imbue that locale on std::cout since the standard
streams are also created before main is called. The final (?) code is to
be found below.

Sincerely,
Peter Jansson
http://www.jansson.net/
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <locale>
#include <sstream>
#include <string>
std::istream& operator>>(std::istream& s,struct std::tm& t);
std::ostream& operator<<(std::ostream& s,const struct std::tm& t);
int main()
{
using std::cout;
std::locale defloc("");
cout<<"Setting the global locale: "<<defloc.name()<<'\n';
cout.imbue(defloc);
cout<<"Locale of cout: "<<cout.getloc().name()<<'\n';
std::locale::global(defloc);
const std::time_t now=std::time(0),later2day5min(now+2*24*3600+5*60) ;
struct std::tm t=*localtime(&now),t2=*localtime(&later2day5min);
std::ostringstream t2s; t2s<<t2;
std::string dateTimeString(t2s.str());
std::istringstream iss(dateTimeString);
cout<<"Locale of ostringstream: "<<t2s.getloc().name()<<'\n';
cout<<"Locale of istringstream: "<<iss.getloc().name()<<'\n';
cout<<"Date order: ";
const std::time_get<char>&
tg=std::use_facet< std::time_get<char> >(cout.getloc());
switch(tg.date_order()) {
case std::time_base::no_order:
cout<<"no order"; break;
case std::time_base::dmy:
cout<<"dmy"; break;
case std::time_base::mdy:
cout<<"mdy"; break;
case std::time_base::ymd:
cout<<"ymd"; break;
case std::time_base::ydm:
cout<<"ydm"; break;
}
cout<<'\n';
cout<<"Date-time at start: "<<t<<'\n';
iss>>t;
cout<<"Date-time to read from a stream: "<<dateTimeString<<'\n';
cout<<"Date-time after reading from a stream: "<<t<<'\n';
return EXIT_SUCCESS;
}
std::istream& operator>>(std::istream& s,struct std::tm& t)
{
using namespace std;
istream::sentry cerberos(s);
if(cerberos) {
ios_base::iostate err = ios::goodbit;
const time_get<char>& tg=use_facet< time_get<char> >(s.getloc());
typedef istreambuf_iterator<char> ist;
ist from(s),end;
ist last=tg.get_date(from,end,s,err,&t);
++from;
tg.get_time(from,end,s,err,&t);
s.setstate(err);
}
return s;
}
std::ostream& operator<<(std::ostream& s,const struct std::tm& t)
{
using namespace std;
ostream::sentry cerberos(s);
if(cerberos) {
const time_put<char>& tp=use_facet< time_put<char> >(s.getloc());
const char fc(s.fill());
tp.put(s,s,fc,&t,'x');
s<<fc;
tp.put(s,s,fc,&t,'X');
}
return s;
}
Jan 15 '06 #7
I notice that in the implementation of operator <<, there is an oppertunity to specify the format and I have chosen to use "%x %X" to get day, month, two digit year, hour, minutes, seconds.

I can read this with the implemenation of operator>> above. However, apparently operator>> is expecting a four digit year and my (slightly) modified operator << prints a 2 digit year.

How can I specify the format to be used by operator>>?

Thanks,
Siegfried
Feb 22 '06 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: F. Da Costa | last post by:
Hi all, Although i'm not a complete newbie i do feel like one at the moment. This question concerns the use of the ResourceBundle as per the example in the Trail tutorial on java.sun.com (thus...
11
by: Charles L | last post by:
I have read that the inclusion of <fstream.h> makes the inclusion of <iostream.h> unnecessary. Is this correct? Charles L
37
by: Zombie | last post by:
Hi, what is the correct way of converting contents of a <string> to lowercase? There are no methods of <string> class to do this so I fallback on strlwr(). But the c_str() method returns a const...
29
by: Jim Moe | last post by:
Hello, I have been using <q> instead of &quot; for quoting recently. Fortunately not much has been changed since it seems IE does not know what to do with <q>! IE ignores it rather than rendering...
8
by: davihigh | last post by:
My Friends: I am using std::ofstream (as well as ifstream), I hope that when i wrote in some std::string(...) with locale, ofstream can convert to UTF-8 encoding and save file to disk. So does...
0
by: | last post by:
Hi all, running the following code as an console application: #include <locale> #include <iostream> #include <sstream> #include <tchar.h> using namespace std;
1
by: Dancefire | last post by:
Hi, everyone, I'm trying to use std::codecvt<to do the encoding conversion. I am using following code for encoding conversion between wchar_t string and char string(MBCS). I am not sure am I...
11
by: Gerald I. Evenden | last post by:
Working on a Kubuntu 64bit system "c++ (GCC) 4.0.3". The following simple program extracted from p.497 & 499 of N.M.Josurris' "The C++ Standard Library ... " (file t.cpp): 1 #include <string>...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.