Datetimeconverter

Soyez le premier à donner votre avis sur cette source.

Snippet vu 5 377 fois - Téléchargée 18 fois

Contenu du snippet

dateTimeConverter(1) User Commands dateTimeConverter(1)

NAME
dateTimeConverter

SYNOPSYS
dateTimeConverter [-h][-i input_type][-o output_type][-1 format] [-2 format] [-s universalFmt] [-a addvalue] [u addUnit] args

DESCRIPTION
dateTimeConverter is used to convert differents formats of datetime like timestamp or datetime (YYYYMMDDhhmiss) into an other format wich can be
defined by user, it also enable to add some time in different units to get the corresponding datetime or timestamp.

OPTIONS
--dfmt1,-1 FORMAT
input datetime or output format(if input is timestamp) dfmt1 is used to specify the date format.

--dfmt2,-2 FORMAT
output datetime format dfmt2 is used to specify the date format. those args should be either the ouptut format for example in case of conversion
from timestamp to datetime or the input format in case of onversion from datetime to timestamp: if not specified Default is YYYYMMDDhhmiss.
YYYY year 4 digits
DD day 2 digits
MM Month 2 digits
hh hour 2 digits
mi minutes 2 digits
ss seconds 2 digits

--input_type ,-i INPUT_TYPE
type of input :datetime or timestamp.

--universal ,-s STRING_FORMAT
universal output datetime format.
%a Abbreviated weekday name
%A Full weekday name
%b Abbreviated month name
%B Full month name
%c Date and time representation
%d Day of the month (01-31)
%H Hour in 24h format (00-23)
%I Hour in 12h format (01-12)
%j Day of the year (001-366)
%m Month as a decimal number (01-12)
%M Minute (00-59)
%p AM or PM designation
%S Second (00-61)
%U Week number with the first Sunday as the first day of week one (00-53)
%w Weekday as a decimal number with Sunday as0 (0-6)
%W Week number with the first Monday as the first day of week one (00-53)
%x Date representation
%X Time representation
%y Year, last two digits (00-99)
%Y Year
%Z Timezone name or abbreviation
%% A % sign

--output_type ,-o OUTPUT_TYPE
type of output :datetime or timestamp.

--help, -h
print this help.

--add, -a VALUE
value to add.

--add_unit, -u UNIT
unit for value to add : allowed is Day, Month, Year, hour, minute, second.

args values to convert in the specified format.

EXAMPLES:
dateTimeConverter -i datetime -o datetime 20110101120000 -1 YYYYMMDDhhmiss -2 "DD/MM/YYYY hh:mi:ss"
return : 01/01/2011 12:00:00

dateTimeConverter -i datetime -o timestamp 20110101120000
return 1293879600
convert a datetime into timestamp with the default datetime format

dateTimeConverter -i datetime -o timestamp -1 "DD/MM/YYYY hh:mi:ss" "01/01/2011 12:00:00"
return 1293879600
convert datetime into timestamp with a specified user format in input

dateTimeConverter -i datetime -o timestamp -1 "DD/MM/YYYY hh:mi:ss" "01/01/2011 12:00:00" -a 10 -u D
return 1294743600
convert datetime to timestamp with an input specified user format after adding 10 days to the input datetime

dateTimeConverter -i datetime -o datetime -s "%A %B %d %Y %H:%M:%S" -1 "DD/MM/YYYY hh:mi:ss" "10/08/2011 13:34:24" -a 10 -u D
return Saturday August 20 2011 13:34:24
convert a specifed datetime format to an other universal datetime format after adding 10 days to the input datetime

dateTimeConverter -i timestamp -o datetime -s "%A %B %d %Y %H:%M:%S" 12345678 -a 10 -u D
return Tuesday June 02 1970 23:21:18
convert a timestamp to an universal datetime format after adding 10 days to the input timestamp

date +%Y%m%d%H%M%S | xargs dateTimeConverter -i datetime -o timestamp -1 YYYYMMDDhhmiss
return current timestamp

date +%s | xargs dateTimeConverter -i timestamp -o timestamp -a 31 -u D
return timestamp after adding 31 days to the current timestamp

Source / Exemple :


#include <getopt.h>

#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <time.h>

using namespace std;
typedef multimap<string,string> Map;

char units [7]={'D','M','Y','h','m','s',0};

void usage (string prog_name){
    cerr<<"Usage: "<<prog_name;
    cerr<<" [-h][-i input_type][-o output_type][-1 format] [-2 format]";
    cerr<<" [-s FORMAT] [-a addval] [-u unit] args"<<endl;
    cerr<<"    options:"<<endl<<endl;
    cerr<<"    --dfmt1, -1       :  input datetime or output format(if input is timestamp) dfmt1 is used to ";
    cerr<<"specify the date format ";
    cerr<<endl<<endl; 
    cerr<<"    --dfmt2, -2       :  output datetime format dfmt2 is used to ";
    cerr<<"specify the date format"<<endl;
    cerr<<"                         those args should be either the ouptut format"<<endl;
    cerr<<"                         for example in case of conversion from"<<endl;
    cerr<<"                         timestamp to datetime or the input"<<endl;
    cerr<<"                         format in case of onversion from";
    cerr<<" datetime to timestamp:"<<endl;
    cerr<<"                         if not specified Default is YYYYMMDDhhmiss";
    cerr<<endl;
    cerr<<"                            YYYY year 4 digits"<<endl;
    cerr<<"                              DD day 2 digits"<<endl;  
    cerr<<"                              MM Month 2 digits"<<endl; 
    cerr<<"                              hh hour 2 digits"<<endl;   
    cerr<<"                              mi minutes 2 digits"<<endl;
    cerr<<"                              ss seconds 2 digits" <<endl<<endl; 
    cerr<<"    --input_type ,-i  : type of input :datetime or timestamp "<<endl<<endl;
    cerr<<"    --universal ,-s  :  universal output datetime format "<<endl;
    cerr<<"                      %a Abbreviated weekday name"<<endl;
    cerr<<"                      %A Full weekday name"<<endl;
    cerr<<"                      %b Abbreviated month name * Aug "<<endl;
    cerr<<"                      %B Full month name"<<endl;
    cerr<<"                      %c Date and time representation"<<endl;
    cerr<<"                      %d Day of the month (01-31)"<<endl;
    cerr<<"                      %H Hour in 24h format (00-23)"<<endl;
    cerr<<"                      %I Hour in 12h format (01-12)"<<endl;
    cerr<<"                      %j Day of the year (001-366)"<<endl;
    cerr<<"                      %m Month as a decimal number (01-12)"<<endl;
    cerr<<"                      %M Minute (00-59)"<<endl;
    cerr<<"                      %p AM or PM designation"<<endl;
    cerr<<"                      %S Second (00-61)"<<endl;
    cerr<<"                      %U Week number with the first Sunday as ";
    cerr<<"the first day of week one (00-53)"<<endl;
    cerr<<"                      %w Weekday as a decimal number with Sunday as"; 
    cerr<<"0 (0-6)"<<endl;
    cerr<<"                      %W Week number with the first Monday as the ";
    cerr<<"first day of week one (00-53)"<<endl; 
    cerr<<"                      %x Date representation"<<endl;  
    cerr<<"                      %X Time representation"<<endl;  
    cerr<<"                      %y Year, last two digits (00-99) "<<endl;
    cerr<<"                      %Y Year "<<endl;
    cerr<<"                      %Z Timezone name or abbreviation"<<endl;
    cerr<<"                      %% A % sign"<<endl;
    cerr<<endl;
    cerr<<"    --output_type ,-o : type of output :datetime or timestamp " ;
    cerr<<endl<<endl;
    cerr<<"    --help ,-h        : print this help " <<endl<<endl;
    cerr<<"    --add, -a         : value to add "<<endl<<endl; 
    cerr<<"    --add_unit, -u    : unit for value to add "<<endl<<endl; 
    cerr<<"    args              : values to convert in the specified format ";
    cerr <<endl<<endl;
    cerr<<" EXAMPLES:"<<endl;
    cerr<<prog_name<<" -i datetime -o datetime 20110101120000 -1 YYYYMMDDhhmiss";
    cerr<<" -2\"DD/MM/YYYY hh:mi:ss\""<<endl;
    cerr<<" return : 01/01/2011 12:00:00"<<endl<<endl;
    cerr<<prog_name<<" -i datetime -o timestamp 20110101120000";
    cerr<<endl;
    cerr<<"return 1293879600 "<<endl<<endl; 
    cerr<<prog_name<<" -i datetime -o timestamp -1 \"DD/MM/YYYY hh:mi:ss\" ";
    cerr<<"\"01/01/2011 12:00:00\""<<endl;
    cerr<<"return 1293879600 "<<endl<<endl;
    cerr<<prog_name<<" -i datetime -o timestamp -1 \"DD/MM/YYYY hh:mi:ss\" ";
    cerr<<"\"01/01/2011 12:00:00\" -a 10 -u D"<<endl;
    cerr<<"return 1294743600 "<<endl<<endl;
}

int str2int (string s) {
    int i;
    istringstream iss(s);
    iss>>i;
    return i;
}
int timeAdd ( int v,char unit,struct tm * timeinfo){
    
    switch (unit){
        case 'D':
            timeinfo->tm_mday+=v;
            break;
        case 'M':
            timeinfo->tm_mon+=v;
            break;
        case 'Y':
            timeinfo->tm_year+=v;
            break;
        case 'h':
            timeinfo->tm_hour+=v;
            break;
        case 'm':
            timeinfo->tm_min+=v;
            break;
        case 's':
            timeinfo->tm_sec+=v;
            break;
    default: cerr<<"unknown unit :"<<unit<<endl;        
    }
    return mktime (timeinfo);
} 
int toTimestamp(string time, string format,struct tm * timeinfo) {
    time_t tms=0;
    timeinfo=localtime(&tms);
    timeinfo->tm_year =str2int( time.substr(format.find("YYYY"),4)) - 1900;
    timeinfo->tm_mday =str2int( time.substr(format.find("DD")  ,2));
    timeinfo->tm_mon  =str2int( time.substr(format.find("MM")  ,2)) - 1;
    timeinfo->tm_hour =str2int( time.substr(format.find("hh")  ,2));
    timeinfo->tm_min  =str2int( time.substr(format.find("mi")  ,2));
    timeinfo->tm_sec  =str2int( time.substr(format.find("ss")  ,2));
    tms=mktime(timeinfo);
    
    return tms;
}

string toDatetime(string format,struct tm * timeinfo) {
    ostringstream y,d,mo,h,mi,s;
    string tmp=format;
    y<<timeinfo->tm_year + 1900;
    if (timeinfo->tm_mday < 10) d<<"0"<<timeinfo->tm_mday;
    else d<<timeinfo->tm_mday;
    if (timeinfo->tm_mon +1< 10) mo<<"0"<<timeinfo->tm_mon+1;
    else mo<<timeinfo->tm_mon+1;
    if (timeinfo->tm_hour < 10) h<<"0"<<timeinfo->tm_hour;
    else h<<timeinfo->tm_hour;
    if (timeinfo->tm_min < 10) mi<<"0"<<timeinfo->tm_min;
    else mi<<timeinfo->tm_min;
    if (timeinfo->tm_sec < 10) s<<"0"<<timeinfo->tm_sec;
    else s<<timeinfo->tm_sec;
    tmp.replace(tmp.find("YYYY",0),4,y.str());
    tmp.replace(tmp.find("DD",0),2,d.str());
    tmp.replace(tmp.find("MM",0),2,mo.str());
    tmp.replace(tmp.find("hh",0),2,h.str());
    tmp.replace(tmp.find("mi",0),2,mi.str());
    tmp.replace(tmp.find("ss",0),2,s.str());
    return tmp;
}
bool isInMap(Map mm,string s){
    Map::iterator it;
    it=mm.find(s);
    return (it!=mm.end());
}
bool isConvAllowed(Map mm,string s1,string s2){
    Map::iterator it;
    it=mm.find(s1);
    if (it!=mm.end())
        while (it->second!=s2) it++;
         return (it!=mm.end());
    return (it!=mm.end());
}

bool isInUnit(char c){
    char * ref;
    ref=units;
    while (ref){
        if (*ref == c)
            return true;    
        ref++;
    }
    return false;
}

int main (int argc,char** argv) {
    int c;
    int long_opt_index = 0;
    string format1="YYYYMMDDhhmiss";
    string format2="YYYYMMDDhhmiss";
    string addV="0";
    int av=0;
    char addU='D';
    char* universalFmt;
    int flgUnivFmt=0;
    char buffer [100];
    string input_type="";
    string output_type="";
    string progname="dateTimeConverter";
    string stime;
    struct tm * timeinfo;
    time_t rawtime;
    
    Map typesAllowed ;
    typesAllowed.insert(pair<string,string>("datetime","timestamp"));
    typesAllowed.insert(pair<string,string>("timestamp","datetime"));
    typesAllowed.insert(pair<string,string>("timestamp","timestamp"));
    typesAllowed.insert(pair<string,string>("datetime","datetime"));    
    
    static struct option long_options[] = {
            {"dfmt1", 1, 0, '1'},
            {"dfmt2", 1, 0, '2'},
            {"add", 1, 0, 'a'},
            {"add_unit", 1, 0, 'u'},
            {"universal", 1, 0, 's'},
            {"input_type", 1, 0, 'i'},
            {"output_type", 1, 0, 'o'},
            {"help", 0, 0, 'h'},
            {0, 0, 0, 0}
    };
    while ( (c=getopt_long ( argc, argv, "a:i:o:1:2:hs:u:", long_options, 
                                &long_opt_index )) != -1 ) 
        
        switch (c){
            case '1':
                format1=optarg;
                break;
            case '2':
                format2=optarg;
                break;
            case 'i':
                input_type=optarg;
                break;
            case 'o':
                output_type=optarg;
                break;
            case 's':
                flgUnivFmt=1;
                universalFmt=optarg;
                break;
            case 'h':
                usage(progname);
                break; 
            case 'a':
                addV=optarg;
                break;

            case 'u':
                addU=optarg[0];
                break;
            default : return -1;
        }
    if (input_type!="")
    if (!isConvAllowed(typesAllowed,input_type,output_type)){
         cerr<<"Conversion types "<<input_type<<" or "<<output_type;
         cerr<<" are not allowed, please use option -h for help!"<<endl;
         return -1;
    };
    if (addU!='0')
    {
        if (!isInUnit(addU)){
            cerr<<"forbidden unit, please use option -h for help!"<<endl;
            return -1;
        }
        else av=str2int(addV);
    }
    while (optind<argc) {
        stime=argv[optind++];
        if (output_type=="timestamp"){
            if (input_type=="datetime"){
                time (&rawtime);
                timeinfo = localtime ( &rawtime );
                rawtime=toTimestamp(stime,format1,timeinfo);
                if (av!=0){
                    rawtime=timeAdd(av,addU,timeinfo);
                }
                cout<<rawtime<<endl;
            } else {
                time (&rawtime);
                rawtime=str2int(stime);
                timeinfo = localtime ( &rawtime );
                if (av!=0)
                    timeAdd(av,addU,timeinfo);
                stime=toDatetime(format1,timeinfo);
                cout<<toTimestamp(stime,format1,timeinfo)<<endl;
            }
        }
        if (output_type=="datetime"){
            if (input_type=="timestamp"){
                time (&rawtime);
                rawtime=str2int(stime);
                timeinfo = localtime ( &rawtime );
                timeAdd(av,addU,timeinfo);
                if (!flgUnivFmt)
                cout<<toDatetime(format1,timeinfo)<<endl;
                else { 
                    strftime (buffer,100,universalFmt,timeinfo);
                    cout<<buffer<<endl;
                }

            }
            if (input_type=="datetime"){
                time (&rawtime);
                timeinfo = localtime ( &rawtime );
                rawtime=toTimestamp(stime,format1,timeinfo);
                
                timeAdd(av,addU,timeinfo);
                if (!flgUnivFmt)
                    cout<<toDatetime(format2,timeinfo)<<endl;
                else { 
                    strftime (buffer,100,universalFmt,timeinfo);
                    cout<<buffer<<endl;
                }
            }
        }
    }
    return 0;
}

Conclusion :


Cette petite application en ligne de commande sans prétention avait pour but premier de convertir les dates en timestamp et vice versa sous unix, je l'ai ensuite adaptée pour convertir 1 format de date en 1 autre format de date avec la possibilité de manipuler des opération sur les différentes unités de temps au passage.
J'ai voulu crééer cette source pour également expérimenter la librairie getopt.h (gestion des options et arguments des lignes de commandes )
Donc voilà c'est fait en c++ par commodités pour la gestion des entrées sorties. J'ai mis la page de man que j'ai créée en guise de description

A voir également

Ajouter un commentaire

Commentaires

guill76
Messages postés
193
Date d'inscription
mercredi 24 août 2005
Statut
Membre
Dernière intervention
3 juin 2016
-
au temps pour moi alors : le man date n'est pas forcément explicite du coup
cptpingu
Messages postés
3821
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
28 août 2019
85 -
>> j'ai privilégié la rapidité d'écriture à la rigueur
Sans doute, mais écrire "const std::string&" au lieu de "string" n'est pas si handicapant, non ?

>> sinon ctime est largement suffisant et simple pour ça..
Tout dépend de si tu veux faire du C ou du C++. On évite de mélanger C et C++ à moins qu'il y ait une bonne raison. Avec Boost::datetime, il n'y en a pas :)

>> ... pour la commande unix date que j'ai consultée avant d'écrire ce prog,
Attention de bien lire la doc avant d'affirmer quelque chose:

>> elle peut convertir la date courante en timestamp mais ne peut convertir aucune autre date
Mouais...
http://www.christopher.compagnon.name/sitewww/shell-date.html

>> de même elle ne peut convertir aucun timestamp en date
Ah bon ? Et un:
$ date -d @1314697811
Tue Aug 30 11:50:11 CEST 2011

A noter que ces remarques ne remettent pas en cause la qualité de ton programme. C'est d'ailleurs très propre d'avoir fait un man.
guill76
Messages postés
193
Date d'inscription
mercredi 24 août 2005
Statut
Membre
Dernière intervention
3 juin 2016
-
Sur le passage des arguments par référence ( je voulais écrire par copie ) => désolé
guill76
Messages postés
193
Date d'inscription
mercredi 24 août 2005
Statut
Membre
Dernière intervention
3 juin 2016
-
Merci pour ces remarques constructives,
Sur le passage des arguments par référence : j'ai privilégié la rapidité d'écriture à la rigueur (je ne développe pas tous les jours en c voilà la raison), mais j' en suis tout à fait conscient, de même pour le "using namespace std" , pour la différence entre it++ et ++it, j'avais oublié cette subtilité et donc merci pour ce rafraîchissement.

Pour les programmes similaires existants:
j'ai de vagues connaissances de boost mais je ne connaissais pas la bibli datetime, je vais aller y jeter un oeil pourquoi pas! sinon ctime est largement suffisant et simple pour ça..

autrement pour la commande unix date que j'ai consultée avant d'écrire ce prog, elle peut convertir la date courante en timestamp mais ne peut convertir aucune autre date, de même elle ne peut convertir aucun timestamp en date.. voilà
cptpingu
Messages postés
3821
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
28 août 2019
85 -
>> Cette petite application en ligne de commande sans prétention avait pour but premier de convertir les dates en timestamp et vice versa sous unix, je l'ai ensuite adaptée pour convertir 1 format de date en 1 autre format de date avec la possibilité de manipuler des opération sur les différentes unités de temps au passage.

Tu sais que la commande "date" sous Unix, fait déjà tout ça ? En C++, il existe aussi la bibliothèque boost::date_time qui le fait aussi.

>> expérimenter la librairie

La bibliothèque

>> getopt.h
boost::program_option est bien meilleur.

Passons à la critique du code:
- Évite les "using namespace", voir: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace
- Parenthèses non nécessaires pour les return. Ex: return (it!=mm.end()); => return it != mm.end();
- Au lieu de:
cerr<<"Usage: "<second!=s2) it++; // Et si à force de faire it++, on a it > mm.end() ?
return (it!=mm.end()); // Pourquoi y a-t-il deux return (it!=mm.end()) à la suite ?
return (it!=mm.end()); // Pourquoi y a-t-il deux return (it!=mm.end()) à la suite ?
}

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.