Datumstring in Double umwandeln



  • Hallo Zusammen,

    ich möchte einen String, welcher eine Datum/Zeit Angabe darstellt in ein Double Wert umwandeln.

    z.B. "20.10.2016 13:10:22"

    Normalerweise benutze ich die Funktion StrToDateTime().
    Das Ergebnis davon weise ich dann einer Double Variablen zu.

    Problem:
    Wird im Windows Betriebsystem das Datumsformat in den Einstellungen geändert, so erhalte ich beim Aufruf der Funktion StrToDateTime() eine Fehlermeldung,
    dass "20.10.2016 13:10:22" keine gütige Datums-/Zeitangabe sei.

    Hat jemand eine alternative zur Funktion StrToDateTime?

    Gruß



  • Ich weiß nicht was du verwendest aber ich habe das hier gefunden.

    http://docs.embarcadero.com/products/rad_studio/radstudio2007/RS2007_helpupdates/HUpdate3/EN/html/delphivclwin32/SysUtils_GetLocaleFormatSettings.html

    damit die settings abrufen und bei strtodatetime als 2. parameter hinzufügen.

    Hab das aber nicht getestet, da ich diese funktionen nicht kenne.



  • Hallo,

    mr_crabs schrieb:

    Hat jemand eine alternative zur Funktion StrToDateTime?

    Ja - Standard C++!

    Da gibt es den Manipulator std::get_time.
    Und wenn Du aus der Zeitinformation unbedingt einen double machen möchtest, so geht das auch:

    #include <ctime>    // std::tm, mktime
    #include <chrono>   // chrono::duration
    #include <iomanip>  // std::put_time, get_time
    #include <iostream>
    #include <sstream>
    
    typedef std::chrono::system_clock Clock;
    
    int main()
    {
        using namespace std;
        istringstream buf( "20.10.2016 13:10:22" );
        tm aTime;
        if( buf >> get_time( &aTime, "%d.%m.%Y %H:%M:%S" ) )
        {
            auto zeitpunkt = Clock::from_time_t( mktime( &aTime ) );
            typedef chrono::duration< double > Sekunden;
            cout << chrono::duration_cast< Sekunden >( zeitpunkt.time_since_epoch() ).count() << "s" << endl;
        }
        else
            cerr << "Format Fehler" << endl;
        return 0;
    }
    


  • Werner Salomon schrieb:

    Hallo,

    mr_crabs schrieb:

    Hat jemand eine alternative zur Funktion StrToDateTime?

    Ja - Standard C++!

    Da gibt es den Manipulator std::get_time.
    Und wenn Du aus der Zeitinformation unbedingt einen double machen möchtest, so geht das auch:

    #include <ctime>    // std::tm, mktime
    #include <chrono>   // chrono::duration
    #include <iomanip>  // std::put_time, get_time
    #include <iostream>
    #include <sstream>
    
    typedef std::chrono::system_clock Clock;
    
    int main()
    {
        using namespace std;
        istringstream buf( "20.10.2016 13:10:22" );
        tm aTime;
        if( buf >> get_time( &aTime, "%d.%m.%Y %H:%M:%S" ) )
        {
            auto zeitpunkt = Clock::from_time_t( mktime( &aTime ) );
            typedef chrono::duration< double > Sekunden;
            cout << chrono::duration_cast< Sekunden >( zeitpunkt.time_since_epoch() ).count() << "s" << endl;
        }
        else
            cerr << "Format Fehler" << endl;
        return 0;
    }
    

    Der Code gefällt mir! Eine kleine Anmerkung aber noch: duration_cast ist hier überflüssig, denn duration<floating_point_type> kann implizit aus duration<integer_type> erstellt werden. Als Faustregel: duration_cast nur verwenden, wenn die Konvertierung verlustbehaftet ist, z.B. float -> int .
    So würde ich Zeile 18 schreiben:

    cout << Sekunden{zeitpunkt.time_since_epoch()}.count() << "s" << endl;
    


  • hi leute

    gibts sowas aehnliches wie prototype fuer template parameter ?
    also welche memberfunktionen eine klasse haben muss damit sie als template parameter akzeptiert werden kann ?
    aehnlich wie pure-virtual classes zur laufzeit.

    zur veranschaulichung kurzer code:

    struct class_prototype
    {
       auto size(void) const -> int;
       auto convert(int value) const int;
       auto name(void) const -> const char*;
    };
    
    struct korrekter_prototyp
    {
       auto size(void) const -> int;
       auto convert(int value) const int;
       auto name(void) const -> const char*;
    };
    
    struct fehlerhafter_prototyp
    {
       auto size(void) const -> int;
       auto convert(int value) const int;
    };
    
    template<class T>
    struct test_class
    {
       T obj;
    };
    
    ...
    test_class<korrekter_prototyp> test1; // ok
    test_class<fehlerhafter_prototyp> test2; // error
    

    gibt es da eine möglichkeit fuer sowas ?

    Meep Meep



  • Das sollte mit den Concepts in kommeden Standards möglich sein.



  • Man kann soetwas zumindest emulieren:

    #include <iostream>
    #include <string>
    #include <type_traits>
    
    namespace detail {
    	struct any {
    		template <typename T> any(T) { }
    	};
    }
    
    #define GENERATE_HAS_MEM_FUN(fun)\
    template <typename, typename T, typename...>\
    class has_mem_fun_##fun {\
    	static_assert(std::integral_constant<T, false>::value, "has_mem_fun_##fun needs function type as second template parameter");\
    };\
    template <typename T, typename ReturnType, typename ...Args, typename ...TemplateArgs>\
    class has_mem_fun_##fun<T, ReturnType(Args...), TemplateArgs...> {\
    	template <typename U>\
    	static typename std::is_same<decltype(std::declval<U>().fun(std::declval<Args>()...)), ReturnType>::type\
    		test(int);\
    \
    	template <typename U>\
    	static typename std::is_same<decltype(std::declval<U>().template fun<TemplateArgs...>(std::declval<Args>()...)), ReturnType>::type\
    		test(any);\
    \
    	template <typename>\
    	static std::false_type test(...);\
    public:\
    	static constexpr bool value = decltype(test<T>(0))::value;\
    };
    
    #define GENERATE_HAS_MEMBER(mem)\
    template <typename T>\
    struct has_member_##mem##_impl {\
    	template <typename U> static std::true_type overload(decltype(&U::mem));\
    	template <typename> static std::false_type overload(...);\
    	\
    	static constexpr bool result = decltype(overload<T>(nullptr))::value;\
    };\
    template <typename T>\
    struct has_member_##mem : public std::integral_constant<bool, has_member_##mem##_impl<T>::result> { };
    
    #define GENERATE_HAS_TYPE(type)\
    template <typename T>\
    struct has_type_##type##_impl {\
    	template <typename U>\
    	static std::true_type overload(typename U::type*);\
    	template <typename>\
    	static std::false_type overload(...);\
    \
    	static constexpr bool result = decltype(overload<T>(nullptr))::value;\
    };\
    template <typename T>\
    struct has_type_##type : public std::integral_constant<bool, has_type_##type##_impl<T>::result> { };
    
    struct foo {
    	foo() = default;
    	foo(const foo&) = delete;
    	foo(foo&&) = default;
    	foo& operator =(const foo&) = delete;
    	foo& operator =(foo&&) = default;
    	~foo() = default;
    
    	using myType = int;
    	char myMem;
    	int bar(double, std::string&) { }
    };
    
    namespace detail {
    	GENERATE_HAS_MEMBER(myMem);
    	GENERATE_HAS_TYPE(myType);
    	GENERATE_HAS_MEM_FUN(bar);
    }
    
    template <typename T>
    using is_foo_compatible = std::conjunction<std::is_default_constructible<T>,
    										   std::negation<std::is_copy_constructible<T>>,
    										   std::negation<std::is_copy_assignable<T>>,
    										   std::negation<std::is_final<T>>,
    										   std::is_destructible<T>,
    										   detail::has_member_myMem<T>,
    										   detail::has_type_myType<T>,
    										   detail::has_mem_fun_bar<T, int(double, std::string&)>
    										  >;
    int main() {
    	std::cout << std::boolalpha << is_foo_compatible<foo>::value << '\n';
    }
    

    Der Code hat aber einige Schwächen. Er kann z.B. in Memberfunktionen nicht zwischen Referenzen und Nicht-Referenzen unterscheiden, const ignoriert er dabei auch. Zusätzlich ignoriert er, ob eine Memberfunktion virtuell ist oder nicht. Sofern du konstante Member-Funktionen erzwingen willst, muss du entsprechend detail::has_mem_fun_bar<const T, int(double, std::string&) const> schreiben. Falls du kein C++17 hast, musst du std::conjunction und std::negation selber programmieren.



  • lustig. eigendlich haette das ein eigener beitrag werden sollen. hab scheinbar ins falsche fenster geschrieben 😃


Anmelden zum Antworten