#include "machdefs.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#ifdef __MWERKS__
   #include "mwerksmath.h"
//   #include "unixmac.h"
#endif

#define DATIMEPRIVEE
#include "strutil.h"
#include "nbconst.h"
#include "datime.h"


/*       Fonctions de calcule de date et temps (Heure)       */
/* 
++ 
  Module 	Dates (C)
  Lib	LibsUtil
  include	datime.h

	Ce groupe de fonctions permettent de manipuler des dates et heures.
	En particulier, il est possible de calculer l'ecart (en nombre de jours
	ou de secondes separant deux dates, ou le temps sideral correspondant 
	a une date et heure legale. Deux structures simples sont definies
	afin de faciliter le passage des arguments entre differentes fonctions:
	- *JMA* : Jour, Mois, Annee
 	- *HMS* : Heure, Minutes, Secondes

--
*/
/*
++
  Links	Voir aussi:
 Temps Sideral, Universel (C)
--
*/
/*
++
Titre	Quelques Macros 
--
*/

/*
++
  StrgtoJMA(strg, jma)
	Decodage d'une chaine de caracteres "strg" sous forme de "12/3/97" en structure 
	JMA "jma".
  JMAtoStrg(jma, strg)
	Ecrit le contenu de la structure JMA "jma" sous forme de "jj/mm/aaaa" dans la chaine
	de caracteres "strg"
  JMAtoStrgLong(jma, strg)
	Ecriture de date en format long , par ex : "Jeudi , 19 Juin 1997"
  StrgtoHMS(strg, hms)
	Decodage d'une chaine de caracteres "strg" sous forme de "hh:mm:ss 10:43:60.5"
	en structure HMS "hms".
  HMStoStrg(hms, strg)
	Ecrit le contenu de la structure HMS "hms" sous forme de "hh:mm:ss" dans la chaine
	de caracteres "strg"
  StrtoHMS(strg, hms)
	Decodage d'une chaine de caracteres "strg" sous forme de "hh:mm:ss 10:43:60.5"
	en structure HMS "hms" avec gestion des signes (decodage correcte de -44:30:05.23)
  HMStoStr(hms, strg)
	Ecrit le contenu de la structure HMS "hms" sous forme de "hh:mm:ss" dans la chaine
	de caracteres "strg" avec gestion des signes
--
*/

void StrtoHMS(char *s,HMS* h)
/* On ne peut pas ecrire 1:-05:-45 pas gere et debile! (mn et sec >=0.)  cmv 12/8/97 */
{
int imoins, i2pt;
h->Heures = h->Minutes = 0; h->Secondes = 0.;
/* decodage de la chaine de characteres */
sscanf(s,"%d:%d:%lf", &(h->Heures),&(h->Minutes),&(h->Secondes));
/* cas du type 5:34:45.5 */
if( h->Heures > 0 ) return;
/* cas du type -5:34:45.5 */
if( h->Heures < 0 ) {
  h->Minutes *= -1; h->Secondes *= -1.;
  return;
}
/* Ici les Heures sont donc nulles "0:..." ou "-0:..." */
/* on n'a donne que l'heure nulle cas "0" ou "-0" sans ":" (idiot mais bon!) */
i2pt = posc(s,':');
if( i2pt < 0 ) return;
/* Ici on a au moins un ou 2 ":" */
/* cas du type 0:34:45.5 ou 0:0:45.5 sans signe - */
imoins = posc(s,'-');
if( imoins < 0 ) return;
/* cas du type -0:34:45.5 ou -0:0:45.5, le signe - n'est pas decode par sscanf */
if( imoins < i2pt ) {   /* on a donne -0:34 ou -0:34:45.5 */
  h->Minutes *= -1; h->Secondes *= -1.;
  return;
}
/* Ici il reste les cas mal codes ou le signe "-" est n'importe ou! */
/* On laisse le decodage par sscanf */
return;
}


void HMStoStr(HMS h,char *s)
/* L'ecriture est forcee a h:mn:sec avec mn et sec >=0  cmv 12/8/97 */
{
double v;
v = HMStoH(h);
h =  DoubletoHMS(v);
if( v < 0. ) {
  h.Heures *= -1; h.Minutes *= -1; h.Secondes *= -1.;
  sprintf(s,"-%02d:%02d:%04.1f", h.Heures,h.Minutes,h.Secondes);
} else {
  sprintf(s,"%02d:%02d:%04.1f", h.Heures,h.Minutes,h.Secondes);
}
}

/* Nouvelle-Fonction */
int NbJourMois(int a, int m)
/* Retourne le nombre de jours dans le mois m, annee a */
{
if(a<100) a+=1900;
if( m<1 || m>12 ) return(-1);
m--;
if(m!=1) return(NbJoMois[m]);
/* traitement du mois de fevrier bissextile ou non */
if(  ((a%4==0) && (a%100!=0))
  ||       (a%400==0)         ) return(NbJoMois[m]+1);
else return(NbJoMois[m]);
}

/* Nouvelle-Fonction */
long JMAtoJ(JMA jma)
/*           Calcule le Nb. de jours ecoules depuis 0 Jan 1901         */
/*   Si annee < 100  On considere annee = annee+1900  (1900-1999)      */

{
long rc,nban;
int i;

/* Protection */
if ( (jma.Mois < 1) || (jma.Mois > 12) )  jma.Mois = 1;
if ( (jma.Jour < 1) || (jma.Jour > 31) )  jma.Jour = 1;

if (jma.Annee < 100)  jma.Annee+=1900;
nban = jma.Annee - 1901;

/*  Annee Normale = 365 Jours - Bissextile = 366 Jours    */
/*  366 Jours  :  Divisible par 4 et non divisible par 100  (1972,1976)   */
/*             :  Divisible par 400 (1900 Non-Biss. et 2000 Biss.)        */

if (nban >= 0)  
  rc = nban*365 + (nban/4) - (nban/100) + ((nban+300)/400);
else 
  rc = nban*365 + (nban/4) - (nban/100) + ((nban-300)/400);

/*    Comptabilisation du nb. des jours des mois ecoule   */
for (i=1; i<jma.Mois; i++)  rc += NbJourMois(jma.Annee, i);
rc += jma.Jour;

return(rc);
}

/* Nouvelle-Fonction */
JMA JtoJMA(long j)
/* retourne la date correspondant a j jours ecoules depuis le 0/1/1901 */
{
long i;
int inc,m;
JMA buf;

inc = (j>=0) ? 1 : -1;
buf.Jour = buf.Mois = 1; buf.Annee = 1901;

/* recherche de l'annee */
for(;;) {
  i = j-JMAtoJ(buf);
  if( i==0 ) return(buf);
  if( inc*i<0 ) {
    /* printf("...annee j=%ld scan=%ld test=%ld\n"
          ,j,JMAtoJ(buf),inc*i); */
    break;
  }
  buf.Annee += inc;
}
if(inc>0) buf.Annee--;
/* printf("Annee trouvee: %d\n",buf.Annee); */

/* recherche du mois */
for(m=1;m<=12;m++) {
  buf.Mois=m;
  i = j-JMAtoJ(buf);
  if( i==0 ) return(buf);
  if(i<0) {
    /* printf("...mois j=%ld scan=%ld test=%ld\n"
          ,j,JMAtoJ(buf),i); */
    buf.Mois--;
    break;
  }
}
/* printf("Mois trouve: %d\n",buf.Mois); */

/* recherche du jour */
for(m=1;m<=31;m++) {
  buf.Jour=m;
  i = j-JMAtoJ(buf);
  if( i==0 ) return(buf);
}
/* printf("Jour trouve: %d\n",buf.Jour); */

/* on a pas trouve !!! normallement impossible! */
printf("**** JtoJMA_Erreur: date non trouvee j=%ld ****\n",j);
buf.Jour = buf.Mois = 1; buf.Annee = 0;
return(buf);
}

/* Nouvelle-Fonction */
int NumJour(JMA jma)
/*        Cette fonction calcule le numero de jour de la semaine    */
/*        (Lundi=1 .. Dimanche=7)                                   */

{
int l;

/*  On appelle JMAtoJ() pour avoir le nb de jours ecoule depuis 1/01/1901  */
/*  Le premier janvier 1901 etait un Mardi (JMAtoJ = 1 , NumJour = 2)      */
l = JMAtoJ(jma)%7 ;
if (l >= 0)  return(l+1);
else return(l+8);
}

/* Nouvelle-Fonction */
JMA JsmmaatoJMA(int nj, int mm, int aa)

/*   Pour "nj=kj*10+jj", calcule la date correspondant au "kj" eme 
     jour "jj" (1 .. 7 - Lundi .. Dimanche) du mois mm , annee aa
     Si "nj" est negatif ->  Dernier jour "jj". Si "kj=0", premier jour "jj".
     Si "kj" ne peut etre atteint -> Dernier jour "jj".
     Si annee "aa" <= 99   ->  annee de 1901 - 1999       */

{
JMA  jma;
int i,k;
int jj, kj;

kj = nj/10;
jj = nj%10;
if (kj < 0)  kj = 0;

if (mm > 12)  mm = 12;
if (mm < 1 ) mm = 1;
if (aa < 100)  aa += 1900;
jma.Mois = mm;
jma.Annee = aa;

if (kj == 0) {
  if (jj >= 0)  {      /*   Premier jour du mois   */    
    if (jj > 7)  jj = 7;
    if (jj < 1)  jj = 1;
    jma.Jour = 1;
    i = NumJour(jma);
    if (i > jj)  jma.Jour = (7-i)+jj+1;
    else jma.Jour = 1+(jj-i);
    }
  else   {             /*   Dernier jour du mois   */
    jj = -jj;
    if (jj > 7)  jj = 7;
    if (jj < 1)  jj = 1;
    jma.Jour = NbJourMois(aa,mm);  
    i = NumJour(jma);
    if (i >= jj)   jma.Jour -= (i-jj);
    else  jma.Jour -= (7+i-jj);
  }
}
else {  /*  On demande le kj eme jour jj du mois  */
  if (jj > 7)  jj = 7;
  if (jj < 1)  jj = 1;
  k = 0;
  for(i=1; i<=NbJourMois(aa,mm); i++) {
    jma.Jour = i;
    if (NumJour(jma) == jj)  k++;
    if (k == kj)  break;
  }
/*  On n'a pas kj jour jj ds ce mois, on renvoie le dernier jj */
  if (k<kj) return(JsmmaatoJMA(-jj, mm, aa));  
}

return(jma);
}

JMA JApmmaatoJMA(int nj, int mm, int aa)
/*    Pour "nj=dd*10+jj", calcule la date correspondant au jour
      "jj" (1 .. 7 - Lundi .. Dimanche) du mois "mm" , annee "aa"
      se trouvant apres (ou egal a) la date "dd/mm/aa" .
      Si annee "aa" <= 99   ->  annee de 1901 - 1999       */
{
int i, dd, jj;
JMA jma;

if (nj < 0) nj = -nj;
if (nj < 1) nj = 1;
dd = nj/10;
jj = nj%10;
for(i=1; i<=6; i++) {
  jma = JsmmaatoJMA(jj+10*i, mm, aa);
  if(jma.Jour >= dd) return(jma);
}
printf("JApmmaatoJMA(%d...) Erreur / Pas de jour %d >= %d/%d/%d\n", nj, jj,dd, mm, aa);
jma.Jour = jma.Mois = jma.Annee = 0;
return(jma);
}

/* Nouvelle-Fonction */
double HMStoH(HMS hms)

/* Cette fonction calcule le nb d'heures en decimales pour hms */
/* Heures/Minutes/Secondes peuvent etre +/- avec toutes les combi possibles */
{
return ((double)hms.Heures + ((double)hms.Minutes)/60. + hms.Secondes/3600.);
}



/* Nouvelle-Fonction */
double HMStoSec(HMS hms)
/*    Calcul du nb de secondes pour hms    */
/* Heures/Minutes/Secondes peuvent etre +/- avec toutes les combi possibles */
{
return ((double)hms.Heures*3600. + (double)hms.Minutes*60. + hms.Secondes);
}

/* Nouvelle-Fonction */
long DatetoSec(char const* date, char const* heure)
/*   Calcul du nombre de secondes correspondant a date/heure    */
/*  a partir de l'origine 1er Janv 1990  0H00                   */
/*  Date entre 1930 - 2050                                      */
{
JMA jma,jma0;
HMS hms;
long dj;

StrgtoJMA(date,jma);   StrgtoHMS(heure,hms);
StrgtoJMA("01/01/1990",jma0);
dj = JMAtoJ(jma) - JMAtoJ(jma0);
if (dj < -24000)  return(-0x7FFFFFFF);
if (dj > 24000)  return(0x7FFFFFFF);
return( dj*3600*24 + (int)(HMStoSec(hms)) );    
}

/* Nouvelle-Fonction */
long DatetoSecOff(char const* date, char const* heure)
{
JMA jma,jma0;
HMS hms, hms0;
long dj,tdec;

StrgtoJMA(date,jma);   StrgtoHMS(heure,hms);
StrgtoJMA("01/01/1990",jma0);   StrgtoHMS("00:00:00",hms0);
dj = JMAtoJ(jma) - JMAtoJ(jma0);
if (dj < -24000)  return(-0x7FFFFFFF);
if (dj > 24000)  return(0x7FFFFFFF);

/* H_vrai+TOff=H_leg : H_vrai-H_vrai0 = (H_leg-TOff)-(H_leg0-TOff0) */
tdec  = 3600*(TLegOffset(jma, hms)-TLegOffset(jma0, hms0));

dj = dj*3600*24 + (int)(HMStoSec(hms)) - tdec;
return(dj);    
}

/* Nouvelle-Fonction */
HMS HtoHMS(double h)
/* Heures decimales en H , M , Sec  Il y a un modulo 24  */
/* la sortie est telle que 0 <= heures < 24 */
{
HMS hms; 

while (h < 0.) h += 24.;
  
hms.Heures = (int) h;
h = (h-hms.Heures)*60.;
hms.Minutes = (int) h;
hms.Secondes = (h-hms.Minutes)*60.;
hms.Heures = hms.Heures % 24;

return(hms);
}

/* Nouvelle-Fonction */
HMS DtoDMS(double h)
/* Degres decimaux en D , M , Sec  Il y a un modulo 360  */
/* la sortie est telle que -180 < deg <= 180. */
{
HMS hms;
int sgn = 1;

while (h > 180.) h -= 360.;
while (h <= -180.) h += 360.;
if( h < 0. ) {h *= -1.; sgn = -1;}
  
hms.Heures = (int) h;
h = (h-hms.Heures)*60.;
hms.Minutes = (int) h;
hms.Secondes = (h-hms.Minutes)*60.;
hms.Heures = hms.Heures % 360;

if( sgn<0 ) {hms.Heures *= -1; hms.Minutes *= -1; hms.Secondes *= -1.;}
return(hms);
}

/* Nouvelle-Fonction */
HMS DoubletoHMS(double h)
/*    Degres/Heures decimaux en D/H , M , Sec  SANS modulo 360/24  */
{
HMS hms;

int sgn = 1;
if( h < 0. ) {h *= -1.; sgn = -1;}

hms.Heures = (int) h;
h = (h-hms.Heures)*60.;
hms.Minutes = (int) h;
hms.Secondes = (h-hms.Minutes)*60.;
hms.Heures = hms.Heures;

if( sgn<0 ) {hms.Heures *= -1; hms.Minutes *= -1; hms.Secondes *= -1.;}
return(hms);
}

/*
++
 Titre	Calcule sur dates et heures
--
*/

/*
++
int NbJourMois(int a, int m)
	Retourne le nombre de jours dans le mois "m", annee "a".
long JMAtoJ(JMA jma)
	Calcule le Nb. de jours ecoules depuis 0 Jan 1901, 
	Si annee < 100  On considere annee = annee+1900  (1900-1999)
JMA JtoJMA(long j)
	Retourne la date correspondant a un nombre de jours "j"
	ecoules depuis le 0 Jan 1901.
int NumJour(JMA jma)
	Calcule le numero du jour de la semaine correspondant a la date indiquee
	par la structure JMA "jma". (Lundi=1 .. Dimanche=7)
JMA JsmmaatoJMA(int nj, int mm, int aa)
	Pour "nj=kj*10+jj", calcule la date correspondant au "kj" eme 
	jour "jj" (1 .. 7 - Lundi .. Dimanche) du mois mm , annee aa
  	Si "nj" est negatif ->  Dernier jour "jj". Si "kj=0", premier jour "jj".
	Si "kj" ne peut etre atteint -> Dernier jour "jj".
	Si annee "aa" <= 99   ->  annee de 1901 - 1999       
JMA JApmmaatoJMA(int nj, int mm, int aa)
	Pour "nj=dd*10+jj", calcule la date correspondant au jour
	"jj" (1 .. 7 - Lundi .. Dimanche) du mois "mm" , annee "aa"
	se trouvant apres (ou egal a) la date "dd/mm/aa" .
	Si annee "aa" <= 99   ->  annee de 1901 - 1999       
double HMStoH(HMS hms)
	Conversion en heures decimales de la structure  "hms"
double HMStoSec(HMS hms)
	Conversion en secondes de la structure HMS  "hms"
HMS HtoHMS(double h)
	Conversion heures en decimales en structure HMS
HMS DtoDMS(double h)
	Conversion degres decimaux en structure HMS (deg,min,sec)
HMS DoubletoHMS(double h)
	Conversion degres/heures decimaux en structure HMS (deg/heure,min,sec)
                   SANS modulo 360/24
long DatetoSec(char const* date, char const* heure)
	Calcule le nombre de secondes correspondant a "date,heure" 
	a partir de l'origine 1er Janv 1990  0H00 ( Date entre 1930 - 2050 )		
long DatetoSecOff(char const* date, char const* heure)
	Calcule le nombre de secondes correspondant a "date,heure" 
	a partir de l'origine 1er Janv 1990  0H00 ( Date entre 1930 - 2050 )
        en tenant compte des decalages des heures legales.
--
*/



/*   Variables contenant les informations pour conversion  */
/*  Temps Legal <> TU <> Temps solaire moyen               */

static double  TSolMOff = 0.;     /*  TSol.Moyen - TU  (en heures) */
static char SiteName[128];           /*  Nom de site  */

static struct
  {
  char fg;         /*  Flag (=A ou B) Type de specification  */
  int jj[2];       /*  Numero ou date du jour                */
  int mm[2];       /*  Mois    */
  int Off[3];      /*  Decalage = TLegal - TU    */
  }  TLegInfo = {'\0',{0,0},{0,0},{0,0,0}} ;

static HMS HChgH = {0,0,0.} ; /*  Heure de changement d'heure */

/* 
++ 
  Module 	Temps Sideral, Universel (C)
  Lib	LibsUtil
  include	datime.h

	Ce groupe de fonctions permet convertir differentes heures:
	les temps local, le temps universel (TU), le temps legal (TLeg). Il est 
	aussi possible de calculer le temps sideral (TS). 
--
*/
/*
++
  Links	Voir aussi:
  Dates (C)
--
*/
/*
++
 Titre	T-Legal, TU
	Conversion entre l'heure legale, le temps universel (TU) et le temps solaire
	moyen
--
*/

/*
++
SetTSolMOff(double tsmoff, char *name)
	Definit pour un site donne, le decalage T Sol. Moyen - TU (en heures) "tmsoff"
	et le nom du site 
PrtTSolMOff()
	Imprime les infos definis par "SetTSolMOff()"
--
*/

/* Nouvelle-Fonction */
void SetTSolMOff(double tsmoff, char *name)

/*     Offset  T Sol. Moyen - TU (en hh:mm:ss) ,  Nom de site name   */
{
TSolMOff = tsmoff;
strcpy(SiteName,name);
return;
}


/* Nouvelle-Fonction */
void PrtTSolMOff(void)
{
printf("  **Site : %s , T Sol.Moy.-TU  %g  (heures) \n",SiteName,TSolMOff);
return;
}

/*
++
int SetTLegOff(char* dtz, char* dhz)
	Initialise la structure TLegInfo. L'argument *dtz peut etre 
	sous 2 forme differentes et permet de  definir 3 plages 
	de temps avec 3 decalages horaires (nb entier). 
	Les dates pivots sont les jours de changement d'heure a 
	l'heure indiquee par dhz ("hh:mm:ss"), si "dhz==NULL ou 
	chaine vide, alors changement a 0 heure.  
|   1) dtz = "A Off1 j1/m1 Off2 j2/m2 Off3"
|      jx/mx Jour/Mois - Offx : Decalage TLeg - TU                  
|      pour 01/01 <= jj/mm <  j1/m1   ->  Off1 
|           j1/m1 <= jj/mm <  j2/m2   ->  Off2 
|           j2/m2 <= jj/mm <= 31/12   ->  off3 
|   2) dtz = "B off1 Js1/m1 Off2 Js2/m2 Off3"
|      Jsx/mx  Numero du jour de la semaine (Js) et numero du mois
|      Js =  1 ..  7  (Lundi .. Dimanche)  :  1er Jour Js du mois    
|         = -1 .. -7   Dernier jour Js du mois                  
|         = k1 .. k7   k eme jour Js du mois                  
|   3) dtz = "C off1 Js1/m1 Off2 Js2/m2 Off3"
|      Jsx/mx  Numero du jour de la semaine (Js) et numero du mois avec une 
|      precision d'une date butee inferieurs    
|      Js =  ddj ..  (j=1..7  Lundi .. Dimanche)  :  1er Jour j du mois
|      apres (ou egal a) la date dd/mm    
	Retour : 0 si Ok -1 Sinon                                          
void PrtTLegInfo(int aa)	
	Imprime les informations de decalage TLeg ,  TU - Annee "aa"
int  TLegOffset(JMA date, HMS heure)
	Indique le decalage (en nombre d'heures) TLeg-TU	
--
*/

/* Nouvelle-Fonction */
int SetTLegOff(char* dtz, char* dhz)

                        
{
int is;

HChgH.Heures = HChgH.Minutes = 0;
HChgH.Secondes = 0.;

if (dhz) StrgtoHMS(dhz, HChgH);
if ( (HChgH.Heures < 0) || (HChgH.Heures > 23) )
  { HChgH.Heures = HChgH.Minutes = 0;  HChgH.Secondes = 0.; }

is = sscanf(dtz,"%c %d %d/%d %d %d/%d %d", &(TLegInfo.fg), &(TLegInfo.Off[0]), &(TLegInfo.jj[0]),  &(TLegInfo.mm[0]), &(TLegInfo.Off[1]), &(TLegInfo.jj[1]),  &(TLegInfo.mm[1]), &(TLegInfo.Off[2]) );

if ( (TLegInfo.fg != 'A') && (TLegInfo.fg != 'B')
     && (TLegInfo.fg != 'C') )  TLegInfo.fg = '\0';
if (is != 8) TLegInfo.fg = '\0';
if (TLegInfo.fg != '\0') return(0);
else { printf("SetTLegOff()/Erreur %s \n", dtz); return(-1); }
}

/* Nouvelle-Fonction */
void PrtTLegInfo(int aa)

/*    Cette fonction  print les infos de TLegInfo     */
{
int i,k,j;
char ForL[2][128];
JMA jma;

if (TLegInfo.fg == '\0')    printf ("  !!! TlegInfo not set or Error \n");


HMStoStrg(HChgH, ForL[0]);
printf("  ==== TLegInfo : Changement d'heure a %s \n", ForL[0]);
ForL[0][0] = '\0';
if (TLegInfo.fg == 'A')  
  {
  printf("  ---- TLegInfo : Selection par date (Flag = A)  ---- \n");
  printf("   -> 01 Janvier - %d %s   :  %d heures \n",TLegInfo.jj[0], NomMo[TLegInfo.mm[0]-1], TLegInfo.Off[0]);
  printf("   -> %d %s - %d %s  :  %d heures \n",TLegInfo.jj[0], NomMo[TLegInfo.mm[0]-1],TLegInfo.jj[1], NomMo[TLegInfo.mm[1]-1],TLegInfo.Off[1]);
  printf("   -> %d %s - 31 Decembre  :  %d heures \n",TLegInfo.jj[1], NomMo[TLegInfo.mm[1]-1], TLegInfo.Off[2]);
  }

if (TLegInfo.fg == 'B')  
  {
  printf("  --- TLegInfo : Selection par Jour de semaine et mois (Flag = B)  --- \n");
  for (i=0;i<2;i++) {
    k = TLegInfo.jj[i]/10;
    if (k < 1)  k = 1;
    j = TLegInfo.jj[i]%10;
    if (j < 0)  j = -j;
    if (j < 1) j = 1;
    if (j > 7) j = 7;
    if (TLegInfo.jj[i] < 0)  sprintf(ForL[i]," Dernier  %s  de  %s  (KJ=%d)", NomJo[j-1], 
                                     NomMo[TLegInfo.mm[i]-1], TLegInfo.jj[i]);
    else  sprintf(ForL[i]," %d eme  %s  de  %s (KJ=%d)", k, NomJo[j-1], 
                  NomMo[TLegInfo.mm[i]-1], TLegInfo.jj[i]);
    }
  printf(" Butees: %s  -  %s \n", ForL[0], ForL[1]);
  for (i=0;i<2;i++) {
    jma = JsmmaatoJMA(TLegInfo.jj[i], TLegInfo.mm[i], aa);
    JMAtoStrg(jma, ForL[i]);
  }
  printf("   -> 01 Janvier %d - %s  :  %d heures \n",aa, ForL[0], TLegInfo.Off[0]);
  printf("   -> %s - %s  :  %d heures \n",ForL[0], ForL[1], TLegInfo.Off[1]);
  printf("   -> %s - 31 Decembre %d :  %d heures \n",ForL[1], aa, TLegInfo.Off[2]);
 }

if (TLegInfo.fg == 'C')  
  {
  printf("  --- TLegInfo : Selection par Jour de semaine >= dd et mois (Flag = C)  --- \n");
  for (i=0;i<2;i++) {
    k = TLegInfo.jj[i]/10;
    j = TLegInfo.jj[i]%10;
    if (j < 0)  j = -j;
    if (j < 1) j = 1;
    if (j > 7) j = 7;
    sprintf(ForL[i],"1er %s  apres le %d %s ", NomJo[j-1], k, NomMo[TLegInfo.mm[i]-1]);
    }
  printf(" Butees: %s - %s \n", ForL[0], ForL[1]);
  for (i=0;i<2;i++) {
    jma = JApmmaatoJMA(TLegInfo.jj[i], TLegInfo.mm[i], aa);
    JMAtoStrg(jma, ForL[i]);
  }
  printf("   -> 01 Janvier %d - %s  :  %d heures \n",aa, ForL[0], TLegInfo.Off[0]);
  printf("   -> %s - %s  :  %d heures \n",ForL[0], ForL[1], TLegInfo.Off[1]);
  printf("   -> %s - 31 Decembre %d :  %d heures \n",ForL[1], aa, TLegInfo.Off[2]);
 }

return;
}


/* Nouvelle-Fonction */
int  TLegOffset(JMA date, HMS heure)

/*     Cette fonction calcule l'offset   TLeg - TU  pour la date donnee date  */
{
JMA jma1,jma2;
long nbj1,nbj2,nbj;
double decj1, decj2, decj;
int Off;

/*   On recherche l'offset correspondant a la date   */
jma1.Annee = jma2.Annee = date.Annee;
if (TLegInfo.fg == 'A')
/*    Periode defini par des dates ds les mois   */ 
  {
  jma1.Mois = TLegInfo.mm[0];
  jma1.Jour = TLegInfo.jj[0];
  jma2.Mois = TLegInfo.mm[1];
  jma2.Jour = TLegInfo.jj[1];
  }
if (TLegInfo.fg == 'B')
/*    Periodes definies par jour de semaine et mois   */
  {
  jma1 = JsmmaatoJMA(TLegInfo.jj[0],TLegInfo.mm[0],date.Annee);
  jma2 = JsmmaatoJMA(TLegInfo.jj[1],TLegInfo.mm[1],date.Annee);
  }

if (TLegInfo.fg == 'C')
/*    Periodes definies par jour de semaine et mois  avec date inferieure */
  {
  jma1 = JApmmaatoJMA(TLegInfo.jj[0],TLegInfo.mm[0],date.Annee);
  jma2 = JApmmaatoJMA(TLegInfo.jj[1],TLegInfo.mm[1],date.Annee);
  }

nbj = JMAtoJ(date);
nbj1 = JMAtoJ(jma1);
nbj2 = JMAtoJ(jma2);

/*  Les dates pivots sont les jours de changement d'heure a Heure= HChgH */
decj = (double)nbj + HMStoH(heure)/24.;
decj1 = (double)nbj1 + HMStoH(HChgH)/24.;
decj2 = (double)nbj2 + HMStoH(HChgH)/24.;

if ( decj < decj1 )  Off = TLegInfo.Off[0];
else if (decj < decj2)  Off = TLegInfo.Off[1];
     else Off = TLegInfo.Off[2];

/*     Impression de debugging   */
/*Debug--  printf ("   @@@ Debug_TLegOffset (date= %d/%d/%d)  :  %d H. \n",date.Jour,date.Mois,date.Annee,Off);
printf("  @-1 %s , %d %s %d \n", NomJo[NumJour(jma1)-1], jma1.Jour, NomMo[jma1.Mois-1], jma1.Annee) ;
printf("  @-2 %s , %d %s %d \n", NomJo[NumJour(jma2)-1], jma2.Jour, NomMo[jma2.Mois-1], jma2.Annee) ;  --*/


return (Off);
}

/*
++
HMS TLegtoTU(JMA date, HMS TLeg)
	Conversion TLegal en TU pour une date donnée
HMS TUtoTLeg(JMA date, HMS TLeg)
	Conversion TU en TLegal pour une date donnée. L'heure légale calculée
	peut être erronnée autour des dates de changement d'heure.
HMS TUtoTSolM(HMS TU)
	Conversion TU en temps solaire moyen
--
*/

/* Nouvelle-Fonction */
HMS TLegtoTU(JMA date, HMS hmsz)

/*   Cette fonction transforme le temps legal en temps universel   */
{
HMS  TU;
int Off;

Off = TLegOffset(date, hmsz);
TU = hmsz;
TU.Heures -= Off;
if (TU.Heures >= 24)  TU.Heures -= 24;
if (TU.Heures < 0)  TU.Heures += 24;
return(TU);
}



/* Nouvelle-Fonction */
HMS TUtoTLeg(JMA date, HMS hms)

/*   Cette fonction transforme le temps universel en temps legal */
{
HMS  TLeg;
int Off;

Off = TLegOffset(date, hms);    /*  $CHECK$  */
TLeg = hms;
TLeg.Heures += Off;
TLeg.Heures = TLeg.Heures%24;
if (TLeg.Heures < 0)  TLeg.Heures += 24;
return(TLeg);
}


/* Nouvelle-Fonction  */
HMS TUtoTSolM(HMS TU)

/*   Passage  TU  ->  Temps local    */
{
double t;
t = HMStoH(TU) + TSolMOff;
return(HtoHMS(t));
}

/*
++
 Titre	Temps Sideral
|      Jour Sideral = 86400 Sec. Sid.  ( = 24 H Sid. )    
|      Annee Solaire = 365 J 5H 48' 46"  =~  365.2422 J                       
|      Annee Solaire = 365.2422 Jours Solaire Moyen = 366.2422 Jours Sideraux 
|      Jour Sol. Moyem = 24 H Sol. = 24 H Sid. * (366.2422 / 365.2422)        
|      Jour Solaire Moyen = 86636.555359 Sec. Sid. = 24 H 3' 56.555359"       
|      Heure Solaire Moyen = 3609.85647 Sec. Sid.                             
|      Sec. Sol. = 1.0027379 Sec. Sid.                                        
|      Le 1er Janvier 1989 0H TU Il etait 6H 42' 30" GMT_Sideral 
--
*/

/*
++
HMS TLegtoTSid(JMA date, HMS TZ)
	Cette fonction calcule le temps sideral a partir du temps
	legal et de la date
GMST_at_0h_UT(JMA date)
	Cette fonction calcule le temps sideral moyen a greenwich a 0h UT
--
*/

/* Nouvelle-Fonction  */
HMS TLegtoTSid(JMA date, HMS TZ)

/*  Cette fonction  donne le temps sideral a partir du temps legal  */
/*  et la date                                                      */
{
HMS  Orgh,TU,TSid;
JMA  Orgd;
int off;
long lj;
double ts,ratio;

/* Le 1er Janvier 1989 0H TU Il etait 6H 42' 30" GMT_Sideral */
StrgtoJMA("1/1/1989",Orgd);
StrgtoHMS("6:42:30",Orgh);



/*    Nb de jours / Date Origine   */
lj = JMAtoJ(date) - JMAtoJ(Orgd);

/*  On calcule l'heure TU et on tient compte du decalage eventuel de + ou - 1 jour  */
off = TLegOffset(date, TZ);
TU = TZ;
TU.Heures -= off;
if (TU.Heures < 0)  
  {
  lj -= 1;
  TU.Heures += 24;
  }
if (TU.Heures >= 24)  
  {
  lj += 1;
  TU.Heures -= 24;
  }



ratio = ((365.*24.) + 5. + (48. / 60.) + (46. / 3600.)) / 24.;
ratio = (ratio+1) / ratio ;

/*   Calcul du decalage en heures du temps Sideral par rapport a          */
/*   l'origine choisie :  ts                                              */

ts = lj * (24. * (ratio - 1) );
ts += ( TU.Heures * ratio );
ts += ( ( TU.Minutes / 60. ) * ratio );
ts += ( (TU.Secondes / 3600. ) * ratio );

ts += HMStoH(Orgh);

/*   On tient compte de l'offset du temps solaire moyen  */
ts += TSolMOff;

TSid = HtoHMS(ts);
TSid.Heures = TSid.Heures % 24;
if (TSid.Heures < 0)  TSid.Heures += 24;

return(TSid);
}


/* Nouvelle-Fonction  */
HMS GMST_at_0h_UT (JMA date)

/*  Cette fonction  donne le temps sideral moyen a greenwich a 0h UT */
/*                                                       CMV 5/11/93 */
{
HMS Orgh, TSid;
JMA  Orgd;
long lj, ejs;
double js, hs, hs0;

/*  J H ' " sont les vraies valeurs indiscutables (cf metre etalon etc..)  */
/*  Annee Solaire  = 365 J 5H 48' 45.2" =~  365.2421898148 J               */
/*  Annee Siderale = 365 J 6H  9'  9.8" =~  365.2563634259 J               */
/*  Le 1er Janvier 1994 0H TU Il sera 6h 41' 40.4305" GMT_Sideral          */
StrgtoJMA("1/1/1994",Orgd);
StrgtoHMS("6:41:40.4305",Orgh);
hs0 = HMStoH(Orgh);

/*   Nb de jours ecoules depuis la Date Origine */
lj = JMAtoJ(date) - JMAtoJ(Orgd);
/* printf("nombre de jours ecoules depuis 1/1/94 %d\n",lj); */

/*   Nb de jours sideraux depuis la Date Origine */
js = (double) lj * 366.2421898148 / 365.2421898148;
/*   Nb d'heures siderales depuis Date Origine (modulo un jour) */
ejs = (int) js;
hs = js - (double) ejs;
hs *= 24.;
hs += hs0;

TSid = HtoHMS(hs);
/* printf("nombre d'heures siderales depuis la reference (modulo un jour) %d %d %f\n"
         ,TSid.Heures,TSid.Minutes,TSid.Secondes); */

return(TSid);
}

/*
++
HMS TUtoTSid(JMA date, HMS TU)
	Cette fonction calcule le temps sideral GMT a partir du temps
	universel et de la date GMT.
int TSidtoTU(JMA date, HMS TS, HMS *TU1, HMS *TU2)
	Cette fonction calcule les temps universels a partir du temps
	sideral GMT et de la date GMT. Selon la valeur du TS, il peut y avoir
	une ou deux possibilites pour le TU (return code).
--
*/

/* Nouvelle-Fonction  */
HMS TUtoTSid(JMA date, HMS TU)

/*  Cette fonction  donne le temps sideral GMT a partir du temps universel  */
/*  et la date  GMT                                                         */
{
HMS  Orgh,TSid;
JMA  Orgd;
long lj;
double ts,ratio;

/*   Le 1er Janvier 1989 0H TU Il etait 6H 42' 30" GMT_Sideral */
StrgtoJMA("1/1/1989",Orgd);
StrgtoHMS("6:42:30",Orgh);

/*    Nb de jours / Date Origine   */
lj = JMAtoJ(date) - JMAtoJ(Orgd);

ratio = ((365.*24.) + 5. + (48. / 60.) + (46. / 3600.)) / 24.;
ratio = (ratio+1) / ratio ;

/*   Calcul du decalage en heures du temps Sideral par rapport a          */
/*   l'origine choisie :  ts                                              */

ts = lj * (24. * (ratio - 1) );
ts += ( TU.Heures * ratio );
ts += ( ( TU.Minutes / 60. ) * ratio );
ts += ( (TU.Secondes / 3600. ) * ratio );

ts += HMStoH(Orgh);

TSid = HtoHMS(ts);
TSid.Heures = TSid.Heures % 24;
if (TSid.Heures < 0)  TSid.Heures += 24;

return(TSid);
}

/* Nouvelle-Fonction  */
int TSidtoTU(JMA date, HMS TS, HMS *TU1, HMS *TU2)

/*  Cette fonction  donne les temps universels a partir du temps sideral GMT */
/*  et la date GMT                                                           */
{
int rc = 0;
HMS  Orgh,T0;
double ratio,delt,deltt,jsecsid;
char strd[16],strh[16];
/* char strh1[16]; */

TU1->Heures = TU2->Heures = -1;
TU1->Minutes = TU2->Minutes = 0;
TU1->Secondes = TU2->Secondes = 0.;

ratio = ((365.*24.) + 5. + (48. / 60.) + (46. / 3600.)) / 24.;
ratio = (ratio / (ratio+1));
jsecsid = 86400./ratio;

/* temps sideral pour la date a 0h TU */
StrgtoHMS("00:00:00",T0);
Orgh =  TUtoTSid(date,T0);
/* JMAtoStrg(date,strd); HMStoStrg(T0,strh); HMStoStrg(Orgh,strh1);
printf("... date=%s tu=%s -> org_ts=%s\n",strd,strh,strh1); */

/* difference de temps sideral / a 0h TU */
delt = HMStoSec(TS) - HMStoSec(Orgh);
/* printf("... ts=%f org_ts=%f en sec -> delt=%f (jsecsid=%g)\n"
      ,HMStoSec(TS),HMStoSec(Orgh),delt,jsecsid); */

if(fabs(delt)<1.e-10) delt=0.;
if(delt<0.) delt += 86400.;
if( fabs(delt-86400.)<1.e-10 ) delt = 86400. - 1.e-10;
if(delt<0. || delt>=86400.+1.e-10) {
  HMStoStrg(TS,strh);
  JMAtoStrg(date,strd);
  printf("*** BUG *** TSidtoTU_erreur: delt=%g<0. (d=%s,ts=%s) *******\n"
        ,delt,strd,strh);
  return(0);
}

/* difference de temps / a 0h TU 1ere solution */
/* printf("... delt=%f en sec sid",delt); */
deltt = delt*ratio;
*TU1 = SectoHMS(deltt);
*TU2 = *TU1;
rc++;
/* HMStoStrg((*TU1),strh1);
printf("... deltt=%f en sec -> TU1=%s\n",deltt,strh1); */

/* Y a t-il une seconde solution ? */
if(delt>=jsecsid-86400.-1.e-10) return(rc);
delt += 86400.;
deltt = delt*ratio;
*TU2 = SectoHMS(deltt);
/* HMStoStrg((*TU2),strh1);
printf("... deltt=%f en sec -> TU2=%s\n",deltt,strh1); */
rc++;

return (rc);
}

/*
++
void TSidSetupLaSilla()
	Fonction d'initialisation de conversion  de temps sideral et legal 
	pour la ESO-Silla "SetTSolMOff() , SetTLegOff()".
|       Longitude = 70 deg 43.8 min ouest
|       Latitude  = 29 deg 15.4 min Sud    
|       T Sol. Moyen - TU = -4.715333 Heures
|       TLegal-TU : -4 Heures de Mars a Octobre, -3 Heures sinon
|       Changement le 1er dimanche >= 8/03  8/10 a midi (12:00:00)
--
*/

/* Fonction d'initialisation de calcul de temps sideral pour la Silla */
void TSidSetupLaSilla()
{
SetTSolMOff((double)(-4.715333),"La Silla (Chili)");
if (SetTLegOff("C -3 87/3 -4 87/10 -3","12:00:00") != 0)
  printf("  TSidSetupLaSilla / Erreur SetTLegOff \n"); 
/*  Position de l'observatoire */
/* SetObsPos("La Silla (Chili)","O 70:43:48","S 29:15:24",2347);  */
return;
}



/*
++
double ToJulianDay(JMA dateTU, HMS hmsTU);
	Calcul du jour Julien pour une date TU.
	Uniquement valable a partir du 15/10/1582 00:00:00.
--
*/

double ToJulianDay(JMA dateTU, HMS hmsTU)
/* Cf Fundamental astronomie, Springer Verlag 2sd ed.  cmv 4/12/98 */
{
double j_dat_0_ut;
long int f,g,a;
f = (dateTU.Mois>=3) ? dateTU.Annee: dateTU.Annee-1;
g = (dateTU.Mois>=3) ? dateTU.Mois: dateTU.Mois+12;
a = 2 - (int)((double)f/100.) + (int)((double)f/400.);
/* Julian date at 0h UT */
j_dat_0_ut = (int)(365.25*(double)f)+(int)(30.6001*(double)(g+1))+dateTU.Jour+a+1720994.5;
return j_dat_0_ut + HMStoH(hmsTU)/24.;
}

/*
++
int FromJulianDay(double JD,JMA* dateTU, HMS* hmsTU);
	Calcul de la date date et l'heure TU a partir d'un jour Julien.
	Retourne 0 si succes.
--
*/

int FromJulianDay(double JD,JMA* dateTU, HMS* hmsTU)
/* Cf Fundamental astronomie, Springer Verlag 2sd ed.  cmv 4/12/98 */
{
double jd,i,f,a,x,b,c,d,e,h;
if(JD<0.) return 1;

i = JD - (int)(JD);
if(i<0.5) jd = (int)(JD)-0.5; else jd = (int)(JD)+0.5;

i = (int)(jd+0.5);
f = jd+0.5 - i;
if(i<2299161.0) a = i;
else {x = (int)((i-1867216.25)/36524.25); a = i+1.+x-(int)(x/4.);}
b = a+1524.;
c = (int)((b-122.1)/365.25);
d = (int)(365.25*c);
e = (int)((b-d)/30.6001);

x = b-d-(int)(30.6001*e)+f;
dateTU->Jour = (int)(x);

if(e<13.5) dateTU->Mois = (int)(e-1.); else dateTU->Mois = (int)(e-13.);

if(dateTU->Mois>2.5) dateTU->Annee = (int)(c-4716.); else dateTU->Annee = (int)(c-4715.);

hmsTU->Heures = hmsTU->Minutes = 0; hmsTU->Secondes = 0.;
h = (JD-ToJulianDay(*dateTU,*hmsTU)) * 24.;
*hmsTU = HtoHMS(h);

return 0;
}


/*
++
double StrgtoDegDec(char *strg)
	Cette fonction renvoie la valeur decimale en heures
	d'un angle specifie sous forme de [-][+]dd:mm:ss.
--
*/

double StrgtoDegDec(char *strg)
/*         cmv 4/12/98 */
{
int dd,mm;
float ss;
char sgn;
double deg;

dd = mm = 0;
ss = 0.;
sgn = *strg;
if (isdigit(sgn))
  sscanf(strg,"%d:%d:%f",&dd,&mm,&ss);
else
  sscanf(strg+1,"%d:%d:%f",&dd,&mm,&ss);
deg = (double)(dd) + (double)(mm)/60. + (double)(ss)/3600.;
if (sgn == '-')  deg = (-deg);
return(deg);
}

/*
++
char * DegDectoStrg(double deg, char *strg)
	Cette fonction ecrit une valeur en degre decimal sous 
	forme de [-]dd:mm:ss.
--
*/

char * DegDectoStrg(double deg, char *strg)
/*         cmv 4/12/98 */
{
int dd,mm;
float ss;
char sgn;

if (deg < (double)(0.))
  { deg = (-deg) ; sgn = '-' ; }
else sgn = '+';
dd = (int)deg;
deg = (deg-(double)(dd)) * (double)60.;
mm = (int)deg;
ss = (deg-(double)(mm)) * (double)60.;
if (sgn == '-')
  sprintf(strg,"-%d:%d:%f",dd,mm,ss);
else
  sprintf(strg,"%d:%d:%f",dd,mm,ss);
return(strg);
}

/*
++
double EccEarth(JMA dateTU)
	Valeur de l'eccentricite de l'orbite terrestre
	a la date TU ``dateTU''.
--
*/
double EccEarth(JMA dateTU)
/* Cf Fundamental astronomie, Springer Verlag 2sd ed p477 table E10.  cmv 9/12/98 */
{
double JD,T;
HMS hmsTU;
hmsTU.Heures = 12; hmsTU.Minutes = 0; hmsTU.Secondes = 0.;
JD = ToJulianDay(dateTU,hmsTU);
/* T en siecles juliens depuis 31/12/1899 a 12h TU --> JD=2415020. */
T = (JD-2415020.)/36525;
return(0.0167498 - 0.00004258*T - 0.000000137*T*T);
}

/*
++
double ObliqEarth(JMA dateTU)
	Valeur de l'obliquite de l'orbite terrestre
	a la date TU ``dateTU'' (en degres decimaux).
--
*/
double ObliqEarth(JMA dateTU)
/* Cf Fundamental astronomie, Springer Verlag 2sd ed.  cmv 9/12/98 */
/* le 1/1/1900 a 0h00 TU --> jd = 2415020.5 */
{
double jd;
HMS hmsTU;
hmsTU.Heures = hmsTU.Minutes = 0; hmsTU.Secondes = 0.;
jd = ToJulianDay(dateTU,hmsTU) - 2415020.5;
return(23.452294 - 0.00013 *jd/365.25);
}

/*
++
double LongEcPerihelie(JMA dateTU)
	Retourne la Longitude Ecliptique du perihelie de
	l'orbite terrestre a la date TU ``dateTU'' (en degres decimaux).
--
*/
double LongEcPerihelie(JMA dateTU)
/* Cf Fundamental astronomie, Springer Verlag 2sd ed p477 table E10.  cmv 9/12/98 */
{
double JD,T;
HMS hmsTU;
hmsTU.Heures = 12; hmsTU.Minutes = 0; hmsTU.Secondes = 0.;
JD = ToJulianDay(dateTU,hmsTU);
/* T en siecles juliens depuis 31/12/1899 a 12h TU --> JD=2415020. */
T = (JD-2415020.)/36525;
/* l = 101d 13' 07.15" + 6171.77" *T + 1.823" *T^2 */
return(101.218652778 + 1.71438055556*T + 0.000506388889*T*T);
}

/*
++
void EquatToEclip(double a,double d,double* l,double *b,JMA dateTU);
	Renvoie les coordonnees ecliptiques ``l,b'' a partir de
	coordonnees equatoriales ``a,d'' a la date TU ``dateTU''.
	La date permet de corriger la variation annuelle
	de l'obliquite terrestre.
--
*/
void EquatToEclip(double a,double d,double* l,double *b,JMA dateTU)
/* Cf Fundamental astronomie, Springer Verlag 2sd ed p477 table E10.  cmv 9/12/98 */
/* l=[0,360[, b=[-90,90] */
{
double e,sinb,cosb,sinl,cosl;

e = ObliqEarth(dateTU)*DegenRad;
a *= DegenRad; d *= DegenRad;

sinb = sin(d)*cos(e)-cos(d)*sin(e)*sin(a);
if(sinb>1.) sinb=1.; if(sinb<-1.) sinb=-1.;
*b = asin(sinb);
cosb = cos(*b);

*l = 0.;
if(cosb!=0.) {
  sinl = (sin(d)*sin(e)+cos(d)*cos(e)*sin(a))/cosb;
  cosl = cos(d)*cos(a)/cosb;
  if(cosl>1.) cosl=1.; if(cosl<-1.) cosl=-1.;
  *l = acos(cosl);
  if(sinl<0.) *l += M_PI;
  if(*l>2.*M_PI) *l -= 2.*M_PI;
}

*b /= DegenRad;
*l /= DegenRad;
}
