Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Date/heure formatée, sprintf ou strftime ?

2 réponses
Avatar
rtroadec
> ED wrote :
>
>> Targeur fou wrote on 14/01/05 :
>> Je me pose la question suivante : vaut-il mieux utiliser sprintf()
ou
>> strftime() pour formater des dates/heures dans des tampons ? Je
vois
>
> strftime(), c'est fait pour, et il y a un contrôle de la taille.

Oui, d'accord pour utiliser strftime(), mais je ne vois pas à quel
niveau strftime() dispose de plus de contrôle que sprintf() pour la
taille (étant donné que si c'est bien fait, le format passé à
sprintf() définit la taille attendue). Tu as remarqué que je
n'utilisais pas le code de retour de sprintf() (pas bien...), si je
réécris plus convenablement le programme précédent (cf. ci-dessous),
c'est pareil. Ce qui me surprend, c'est que pour la tâche de formatage
de dates/heures, je rencontre vraiment peu cette fonction (strftime())
tandis que des sprintf() j'en vois partout (code datant de 10 ans,
30000 lignes de code). Est-ce dû à l'héritage de C pré-ANSI, y
avait-il des soucis (peut-être encore aujourd'hui) avec strftime() ou
était-ce la méconnaissance de cette fonction à l'époque ? Car je
remplacerais bien tous les sprintf() par strftime() d'une part pour
alléger le code mais aussi pour avoir des formats de date améliorés
avec noms des jours de la semaine et de mois. Mais apparemment, il
faut faire gaffe entre les versions C90 et C99 de strftime() à ce que
je vois comme différences entre mon K&R et une draft de C99, beaucoup
de formats ont été ajoutés.

Regis

_______________________________________

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <limits.h>
#include <errno.h>
#include "dbgtrace.h" /* macros maison FUNCNAME et TRACE_ERR */

#define LG_DATE 8
#define FMTDATE_WITH_SPRINTF 0

long numDateYYYYMMDD(void);

int main(void)
{
long numDate = numDateYYYYMMDD();
printf("Date YYYYMMDD: %ld\n", numDate);
return 0;
}

/**
* numDateYYYYMMDD()
* Returns a numeric date on 8 digits (YYYYMMDD)
* @return numeric date or -1 if failure
*/
long numDateYYYYMMDD(void)
{
time_t calTime;
struct tm * locTime;
char date[LG_DATE+1];
long numDate;
int fmtRc;

FUNCNAME("numDateYYYYMMDD");

/* Gets the calendar time */
calTime = time(NULL);
if (calTime == (time_t)-1)
{
TRACE_ERR("calendar time is unavailable", -1);
}

/* Converts the calendar time into local time */
locTime = localtime(&calTime);

/* Writes the local time in the buffer according to the YYYYMMDD
format */
#ifdef FMTDATE_WITH_SPRINTF
fmtRc = sprintf(date,"%04d%02d%02d\0",
locTime->tm_year+1900,
locTime->tm_mon+1,
locTime->tm_mday)!= LG_DATE);
#else
fmtRc = strftime(date, LG_DATE+1,"%Y%m%d\0",locTime);
#endif

if (fmtRc != LG_DATE)
{
TRACE_ERR("failed to print the formatted date in the buffer",-1);
}

numDate = strtol(date,NULL,10);
if (numDate == LONG_MAX || numDate == LONG_MIN)
{
errno = 0;
TRACE_ERR("the date to long conversion failed", -1);
}

return numDate;
}

2 réponses

Avatar
Emmanuel Delahaye
Targeur fou wrote on 17/01/05 :

Targeur fou wrote on 14/01/05 :
Je me pose la question suivante : vaut-il mieux utiliser sprintf() ou
strftime() pour formater des dates/heures dans des tampons ? Je vois


strftime(), c'est fait pour, et il y a un contrôle de la taille.


Oui, d'accord pour utiliser strftime(), mais je ne vois pas à quel
niveau strftime() dispose de plus de contrôle que sprintf() pour la
taille


Gni ? strftime() a un paramètre 'taille', comme fgets() et
snprintf()... mais pas comme sprintf().


(étant donné que si c'est bien fait, le format passé à
sprintf() définit la taille attendue). Tu as remarqué que je


Euh, non. Il peut y avoir des débordements (valeurs non initialisées,
négatifs traités en unsigned etc.)...

n'utilisais pas le code de retour de sprintf() (pas bien...), si je
réécris plus convenablement le programme précédent (cf. ci-dessous),
c'est pareil. Ce qui me surprend, c'est que pour la tâche de formatage
de dates/heures, je rencontre vraiment peu cette fonction (strftime())


Tu la trouve dans mon code depuis que je l'ai découverte dans les
années 95...

Mais apparemment, il
faut faire gaffe entre les versions C90 et C99 de strftime()


Argh, ils ont osé introduire des incompatibilités ?

à ce que
je vois comme différences entre mon K&R et une draft de C99, beaucoup
de formats ont été ajoutés.


Si c'est 'ajouté', ça va. Du moment que ça reste compatible avec C90...

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Mal nommer les choses c'est ajouter du malheur au
monde." -- Albert Camus.



Avatar
Antoine Leca
En , Emmanuel Delahaye va escriure:
Gni ? strftime() a un paramètre 'taille', comme fgets() et
snprintf()... mais pas comme sprintf().


Certes, mais sa signification n'est pas la même. Et la logique pour arriver
à faire rentrer la chaîne produite dans le tampon (à coup de je double la
taille, par exemple) est plus complexe...

Mais apparemment, il
faut faire gaffe entre les versions C90 et C99 de strftime()


Argh, ils ont osé introduire des incompatibilités ?


%g %G %u %V, très intéressants pour pouvoir écrire une date dans un format
facilement compréhensible par les automates européens.
%E* %O*, important eux pour écrire des dates aux formats utilisés en Asie de
l'Est, voire pour le format anglais formel (%A, %B %Oe).


Si c'est 'ajouté', ça va. Du moment que ça reste compatible avec
C90...


À part cela, la modification porte sur le fait que le comportement est
défini dans C99; par exemple, ce que sort strftime() en locale "C" est
prévisible (et fortement teinté Américain, comme l'étaient la plupart des
implémentations), ce n'était pas le cas en C90.


Antoine