Vous êtes sur la page 1sur 4

From - Wed Nov 13 18:02:54 1996

Path: news.unizar.es!news.rediris.es!minerva.ibernet.es!news.ctv.es!usenet
From: Juan Conejero Gil <skycad@ctv.es>
Newsgroups: es.comp.lenguajes.c
Subject: Re: time.h
Date: Tue, 12 Nov 1996 23:51:31 +0100
Organization: AVA/SKYCAD
Lines: 154
Message-ID: <3288FF73.493@ctv.es>
References: <3288E796.5E0D@arrakis.es>
NNTP-Posting-Host: ctv4095.ctv.es
Mime-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit
X-Mailer: Mozilla 2.01Gold (Win95; I)
Felipe Nez wrote:

> Estoy haciendo una clase que te permite leer y modificar la fecha y
> hora. Quiero que compile en DOS, UNIX y MAC, y a la hora de leer la hora
> no hay problema: uso time para obtener los segundos desde el Epoch, y
> luego localtime para convertirlo en la fecha y hora.
> Pero para cambiar la hora solo conozco stime que admite como argumento
> un time_t que represente los segundos desde el Epoch. Lo que no se es
> cmo pasar la fecha y hora que quiero introducir a segundos desde el
> maldito 1970.
> Me han sugerido que haga los clculos, pero no se por donde empezar.
> Podra darme alguien alguna solucin?
> Muchas gracias.
>
> judas@arrakis.es
mktime() de la biblioteca estndar, tal como te ha sugerido J.A. Gutirrez, es una
solucin transportable. Sin embargo, creo que una solucin ms general al problema que

planteas, y de paso a cualquier problema relacionado con fechas e intervalos de
tiempo,
puede ser de gran inters.
El tratamiento riguroso del tiempo requiere el manejo de algoritmos relacionados
con
nmeros de da juliano. El nmero de da juliano (JD) correspondiente a un instante dado

se define como el nmero de das transcurridos desde el 1.5 de enero de -4712 en cua
lquier
escala de tiempo. JD se emplea principalmente en astronoma para la expresin del ti
empo,
ya que al ser una numeracin lineal, independiente de meses y aos, simplifica de fo
rma
esencial la medida de intervalos de tiempo as como todos los algoritmos en los qu
e el
tiempo es la variable independiente.
Los algoritmos relacionados con el nmero de da juliano que implementamos aqu son
debidos a Jean Meeus (1) y son vlidos para todo JD >= 0, es decir, para cualquier

instante igual o posterior a -4712 enero 1.5. Estos algoritmos tienen adems en cu
enta la
Reforma Gregoriana del calendario, de manera que el da siguiente al 4 de octubre
de 1582
es el 15 de octubre de 1582, o principio del calendario gregoriano.
Las fechas son manipuladas por estos algoritmos en el sistema astronmico de enume
racin
de fechas. Segn este sistema, la fecha anterior al 1 de enero del ao 1 es el 31 de

diciembre del ao 0, y la fecha anterior al 1 de enero del ao 0 es el 31 de diciemb
re del
ao -1. Este sistema es diferente del empleado muchas veces por los historiadores,
que
consideran el ao -1 como inmediatamente anterior al ao 1, ignorando el ao 0, con la

consiguiente incorreccin aritmtica.
En las funciones que se definen a continuacin el parmetro 'DD' es el da de una fech
a
con decimales; por ejemplo, para una fecha cualquiera a las 14h57m39s,
DD = da_de_la_fecha + 14/24 + 57/1440 + 39/86400.
MM es el nmero del mes de la fecha, desde 1=enero hasta 12=diciembre.
(1) Meeus, Jean. Astronomical Algorithms. Willmann-Bell, 1991. pp 59-63.
/* -*- begin code -*- */
/*
* Clculo del JD para la fecha dada por YY, MM, DD (ao, mes, da).
*/
double DateToJD( int YY, int MM, double DD )
{
int Y = YY, M = MM;
double JD;
if ( MM <= 2 )
{
Y--;
M += 12;
}
JD = (long)(365.25*(Y+4716)) + (long)(30.6001*(M+1)) + DD - 1524.5;
if ( YY > 1582 || YY == 1582 && (MM > 10 || MM == 10 && DD >= 15) )
{
long A = Y/100;
return JD + (2 - A + (A >> 2));
}
return JD;
}
/*
* Clculo de los elementos YY, MM, DD (ao, mes, da) de la fecha
* correspondiente a un JD. La funcin asegura que los elementos MM y DD son coher
entes,
* es decir, tiene en cuenta el nmero de das para cada mes, aos bisiestos, etc.
*/
void JDToDate( double JD, int *YY, int *MM, double *DD )
{
long Z, A, B, D;
int C, E;
JD += 0.5;
A = Z = JD;
if ( Z >= 2299161L )
{
long a = (Z-1867216.25) / 36524.25;
A += 1 + a - (a >> 2);
}
B = A+1524;
C = (B-122.1) / 365.25;
D = 365.25*C;
E = (B-D) / 30.6001;
*DD = B - D - (long)(30.6001*E) + (JD-Z);
*MM = E - ((E < 14) ? 1 : 13);
*YY = C - ((*MM > 2) ? 4716 : 4715);
}
/* -*- end code -*- */
Algunas ejemplos sencillos de aplicacin de JD:
* Clculo del intervalo Delta en das transcurrido desde una fecha dada por Y1, M1,
D1 a
otra fecha dada por Y2, M2, D2:
Delta = DateToJD( Y2, M2, D2 ) - DateToJD( Y1, M1, D1 );
Para expresar Delta en segundos (pregunta original), basta con hacer Delta*86400
L.
Naturalmente, Delta < 0 si {Y1,M1,D1} es posterior a {Y2,M2,D2}.
* Clculo de la fecha Y2, M2, D2 que resulta al transcurrir un intervalo Delta en
das a
partir de una fecha Y1, M1, D1 (problema inverso al anterior):
JDToDate( DateToJD( Y1, M1, D1 )+Delta, &Y2, &M2, &D2 );
* Clculo del da de la semana W correspondiente a una fecha cualquiera Y, M, D:
W = (int)((unsigned long)(DateToJD( Y, M, D )+1.5) % 7);
0 <= W < 7, donde 0=domingo, 1=lunes,... 6=sbado
* Clculo del nmero N del da del ao al que corresponde una fecha Y, M, D:
N = 1 + (int)(DateToJD( Y, M, D ) - DateToJD( Y, 1, 1 ));
El da 1 del ao es el 1 de enero. El ltimo da del ao es 365 366, para aos normales
o bisiestos, respectivamente.
* Hacer un calendario perpetuo (al menos desde -4712) es trivial mediante JD.
Para transformar una fraccin de da (parte fraccionaria del argumento DD en las fun
ciones
anteriores) en hh (horas), mm (minutos) y ss (segundos):
#include <math.h>
/* ... */
double fh = 24 * (DD-(int)DD), fm;
double ss = 60 * modf( 60 * modf( fh, &fh ), &fm );
int hh = (int)fh;
int mm = (int)fm;
--
// ******************************
// Juan Conejero Gil, AVA/SKYCAD
// mailto:skycad@ctv.es
// http://www.ctv.es/USERS/skycad
// ******************************