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 ---- // 7 3477
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
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
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
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;
}
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
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;
}
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
This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
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...
|
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
|
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...
|
by: Jim Moe |
last post by:
Hello,
I have been using <q> instead of " 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...
|
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...
|
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;
|
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...
|
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>...
|
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...
|
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...
|
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...
|
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,...
|
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$) {
}
...
|
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...
|
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
|
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...
|
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...
| |