2017-08-17 9 views
1

Je voudrais convertir les données de chaîne à struct tm (c) ou std::chrono::time_point. Le problème est que je veux travailler la solution pour la libc standard (glibc et musl). J'ai des formats standard d'arbre que je veux analyser.convertir les données/temps en tm/time_point contre musl et glibc. Common way

  1. RFC-1123

    Sun, 6 novembre 1994 08:49:37 GMT

  2. RFC-850

    dimanche », 06-Nov-94 08:49:37 GMT "

  3. format de asctime ANSI C

    Sun 6 novembre 1994" 08:49:37

Est-il possible de le faire fonctionner? std::get_time a un

strptime fonctionne bien (et rapide) sur la glibc, mais échoue contre musl.

Une idée? Je ne veux pas utiliser le flux comme dans get_time. Mais si ce serait nécessaire, ça va. (Il est autorisé à utiliser GCC5> et C++ 11 standard)

Répondre

1

Howard Hinnant's free, open source, header-only, date/time library peut analyser ces formats dans un std::chrono::time_point, même dans le contexte des installations défectueuses get_time et strptime. Cependant, il nécessite l'utilisation de std::istringstream. Voici à quoi il ressemble:

#include "date.h" 
#include <sstream> 

std::chrono::system_clock::time_point 
parse_RFC_1123(const std::string& s) 
{ 
    std::istringstream in{s}; 
    std::chrono::system_clock::time_point tp; 
    in >> date::parse("%a, %d %b %Y %T %Z", tp); 
    return tp; 
} 

std::chrono::system_clock::time_point 
parse_RFC_850(const std::string& s) 
{ 
    std::istringstream in{s}; 
    std::chrono::system_clock::time_point tp; 
    in >> date::parse("%a, %d-%b-%y %T %Z", tp); 
    return tp; 
} 

std::chrono::system_clock::time_point 
parse_asctime(const std::string& s) 
{ 
    std::istringstream in{s}; 
    std::chrono::system_clock::time_point tp; 
    in >> date::parse("%a %b %d %T %Y", tp); 
    return tp; 
} 

Cela peut être exercé comme ceci:

#include <iostream> 

int 
main() 
{ 
    auto tp = parse_RFC_1123("Sun, 06 Nov 1994 08:49:37 GMT"); 
    using namespace date; 
    std::cout << tp << '\n'; 
    tp = parse_RFC_850("Sunday, 06-Nov-94 08:49:37 GMT"); 
    std::cout << tp << '\n'; 
    tp = parse_asctime("Sun Nov 6 08:49:37 1994"); 
    std::cout << tp << '\n'; 
} 

et sorties:

1994-11-06 08:49:37.000000 
1994-11-06 08:49:37.000000 
1994-11-06 08:49:37.000000 

Les drapeaux parse %a et %b sont normalement locale dépendant. Toutefois, si vous compilez cette bibliothèque avec -DONLY_C_LOCALE=1, il devient indépendant des paramètres régionaux. Il devrait donner le même résultat de toute façon. Mais d'un point de vue pratique, si vous compilez sans-DONLY_C_LOCALE=1 et que vous n'obtenez pas les résultats ci-dessus, vous devez soumettre un rapport de bogue à votre fournisseur std :: lib.

Si vous compilez avec-DONLY_C_LOCALE=1 et vous ne recevez pas les résultats ci-dessus, hochet ma cage, et je l'aurai fixe en quelques jours, voire quelques heures.

+0

Merci pour les modifications! –

+0

Merci pour votre réponse! J'ai fait quelques benchmarks sur votre fonction.Je ne comprends pas pourquoi votre solution est plus rapide que 'sprintf' dans le cas RFC850. Même que vous utilisez des flux. Benchmark peut être trouvé [ici] (https://github.com/oktal/pistache/pull/102#issuecomment-322527542). –

+0

Bon à savoir, merci. –