Probleme mit std::get_time


  • Banned

    Hallo,

    Habe Probleme mit std::get_time. Versuchte den Fehler auf Ideone zu reproduzieren. Komisch, dort klappt es.

    #include <iostream>
    #include <sstream>
    #include <ctime>
    //#include <codecvt>
    #include <iomanip>
    #include <locale>
    #include <boost/date_time.hpp>
    //using namespace std;
    
    std::string DateToString(const boost::gregorian::date& date)
    {
    	std::tm tm = to_tm(date);
    
    	std::ostringstream stream;
    	//stream.imbue(std::locale("en_us.utf-8"));
    	stream.imbue(std::locale(""));
    
    	stream << std::put_time(&tm, "%x");
    	
    	std::cout << stream.str() << '\n';
    	
    	return stream.str();
    }
    
    
    boost::gregorian::date StringToDate(const std::string& string)
    {
    	std::istringstream stream(string);
    	//stream.imbue(std::locale("en_us.utf-8"));
    	stream.imbue(std::locale(""));
    	
    	std::tm tm = {};
    	stream >> std::get_time(&tm, "%x");
    
    	boost::gregorian::date ret;
    
    	if (!stream.fail()) 
    	{
    		ret = boost::gregorian::date_from_tm(tm);
    	}
    	else 
    	{
    		ret = boost::gregorian::date(boost::gregorian::not_a_date_time);
    	}
    
    	return ret;
    }
    
    int main() 
    {
    	boost::gregorian::date today(2020, 2, 9);
    	
    	std::string todayString = DateToString(today);
    	auto todayFromString = StringToDate(todayString);
    	DateToString(todayFromString);
    	
    	auto yesterdayFromString = StringToDate("01/09/2020");
    	DateToString(yesterdayFromString);
    	
    	return 0;
    }
    

    Mache jetzt Denkpause ­čś┤ , f├╝r Tipps bin ich dankbar. Danke im voraus.

    Edit: Also das Problem besteht mit msvc immer noch. Anhand eines (identischen) locale
    stream.imbue(std::locale(""))
    und format strings ("%x")
    stream << std::put_time(&tm, "%x")
    stream >> std::get_time(&tm, "%x")

    Soll ein Datum in einen stringstream ausgegeben werden und umgekehrt wieder eingelesen werden. Das Ausgeben klappt, das Einlesen nicht, obwohl locale und format string identisch sind. (Auf Ideone klappt anscheinend beides, aber ich meine glaube nur mit std::locale(""), welches bei meinem OS glaube ich so etwas wie de_ch ist).

    Edit: Also std::get_time f├╝llt die std::tm struct nur bis tm_mday aus, nachher nicht mehr. Und glaube ein failbit wird gesetzt, also fail() vom stringstreamgibt trueaus.

    Habe versucht es weiter auszubessern und nochmals auf Ideone den Fehler zu reproduzieren. Also eben mit Ideone funktioniert es soweit. Ideone hat aber ein anderes locale mit stream.imbue(std::locale("")).

    #include <iostream>
     
    #define BOOST_DATE_TIME_NO_LIB
    #include <boost/date_time.hpp>
     
    #include <sstream>
    #include <locale>
    #include <ctime>
    #include <iomanip>
     
    boost::gregorian::date DateFromString(const std::string& variable);
     
    int main() 
    {
     
    	DateFromString("01/09/2020");
     
     
    	return 0;
    }
     
    boost::gregorian::date DateFromString(const std::string& variable)
    {
    	std::stringstream stream;
    	stream.imbue(std::locale(""));
    	stream << variable;
     
    	bool streamCheck = stream.fail();
     
    	std::tm datetm = {0};
    	stream >> std::get_time(&datetm, "%x");
     
    	std::cout << datetm.tm_mday << '\n' << datetm.tm_mon << '\n' << datetm.tm_year << '\n';
     
    	boost::gregorian::date datevalue;
     
    	if (!stream.fail()) 
    	{
    		datevalue = boost::gregorian::date_from_tm(datetm);
    	}
    	else 
    	{
    		datevalue = boost::gregorian::date(boost::date_time::not_a_date_time);
    	}
     
    	return datevalue;
    }
    

    Also in der Referenz en.cppreference.com/w/cpp/locale/locale hat es bei den Examples:

     std::wcout << "User-preferred locale setting is " << std::locale("").name().c_str() << '\n';
    

    wobei User-preferred locale setting is en_US.UTF8 als possible output angegeben ist. Dr├╝cke ich auf run steht User-preferred locale setting is C. W├Ąhle ich clang (C++14) steht nichts mehr, nichts mehr steht auch, wenn ich dies lokal auf meinem Computer ausprobiere.

    Unter en.cppreference.com/w/cpp/locale/time_get/get_date steht

    1. Reads successive characters from the sequence [beg, end) and parses out the calendar date value using the default format expected by this locale, which is the same format as

    "%x"

    (until C++11)

    "%d/%m/%y", "%m/%d/%y", "%y/%m/%d", and "%y/%d/%m", depending on date_order()

    (since C++11)

    as used by the functions std::get_time(), get(), and the POSIX function strptime()

    Das "%x" wird seit C++11 ├╝berschrieben ­čÖő­čĆ╗ÔÖé ? Aber auch das Trennzeichen (/) ist ja anders?


  • Banned

    Tag 3: Versuchte noch das Trennzeichen zu vereinheitlichen:

    for (size_t index = 0; index < date_string.size(); ++index)
    {
    	if (!std::isdigit(date_string[index]))
    	{
    		date_string[index] = '/';
    	}
    }
    

    und dann ├╝ber std::time_get date_order die richtige Reihenfolge der Anordnung von Tag, Monat, Jahr zu finden. Bekam aber falsche Reihenfolgen, obwohl es bei time_put aufgrund desselben locals die Reihenfolge (und eigentlich auch das Trennzeichen) ausgab.

    Daf├╝r hat es auf der verlinkten Website bei den Examples ein Link zu einem Bug. Dort ist eine library https://github.com/HowardHinnant/date in einem Kommentar verlinkt. Habe es mir noch nicht genau angeschaut, aber ich finde es sieht vielversprechend aus.

    Edit: Anscheinend ├╝bernimmt die library die bugs von std::time_get week_day_parse_bug.

    date::year_month_day date;
    std::stringstream istrm(date_string);
    istrm >> date::parse("%x", date);
    std::cout << "parsed date " << date << '\n';
    

    parse h├Ątte es, funktionierte bei mir aber nicht mit std::locale::global(std::locale(""));.


  • Banned

    Werde einen Trick anwenden. Da std::put_time(&tm, "%x") funktioniert, ├╝bergebe ich ein Datum mit voneinander unterschiedlichen Ziffern, also 23.04.1999. Aus dem string kann ich dann Reihenfolge und Trennzeichen auslesen.


Log in to reply