GregorianCalendarConverter.cc

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021    Author: Laurent Pereira
00022 */
00023 
00024 
00025 
00026 #include "GregorianCalendarConverter.h"
00027 
00028 #include <ctype.h>
00029 
00030 #include <eyedbconfig.h>
00031 #if TIME_WITH_SYS_TIME
00032 #include <sys/time.h>
00033 #include <time.h>
00034 #else
00035 #if HAVE_SYS_TIME_H
00036 #include <sys/time.h>
00037 #else
00038 #include <time.h>
00039 #endif
00040 #endif
00041 
00042 namespace eyedb {
00043   //
00044   // Constants
00045   //
00046 
00047   // The julian day for the day 1970-01-01
00048   const eyedblib::int32 JULIAN_19700101 = 2440588;
00049 
00050   const int MAX_STRING_DATE = 16;     // 16 > (-)YYYYYY + - + MM + - + dd + '\0'
00051   //      =  1 + 6    + 1 +  2 + 1 +  2 +  1
00052   //      = 14
00053 
00054   //
00055   // GregorianCalendarConverter methods
00056   //
00057 
00058   GregorianCalendarConverter::GregorianCalendarConverter()
00059   {
00060     this->string_date = new char[MAX_STRING_DATE]; 
00061     this->tmp_year = 0;
00062     this->tmp_day = 0;
00063     this->tmp_month = 0;
00064   }
00065 
00066 
00067   GregorianCalendarConverter::~GregorianCalendarConverter()
00068   {
00069     delete this->string_date;  
00070   }
00071 
00072 
00073   // algorithms from http://hermetic.magnet.ch/cal_stud/jdn.htm
00074   // ref : Henry F. Fliegel and Thomas C. Van Flandern
00075   void
00076   GregorianCalendarConverter::jday2calendar(const eyedblib::int32 julian, eyedblib::int32 * year, eyedblib::int16 * month, eyedblib::int16 * day)
00077   {
00078     // check return values
00079 
00080     if(year == 0)
00081       {
00082         year = &tmp_year;
00083       }
00084     if(month == 0) 
00085       {
00086         month = &tmp_month;
00087       }
00088     if(day == 0)
00089       {
00090         day = &tmp_day;
00091       }
00092 
00093     // check the julian day number
00094     if( julian < 0 )
00095       {
00096         // set the date to julian=0
00097         *year = -4713;
00098         *month = 11;
00099         *day = 24;
00100 
00101         return;
00102       }
00103 
00104   
00105     // run the conversion algorithm
00106 
00107     eyedblib::int32 l = 0;
00108     eyedblib::int32 n = 0;
00109     eyedblib::int32 i = 0;
00110     eyedblib::int32 j = 0;  
00111 
00112     l = julian + 68569;
00113     n = ( 4 * l ) / 146097;
00114     l = l - ( 146097 * n + 3 ) / 4;
00115     i = ( 4000 * ( l + 1 ) ) / 1461001;
00116     l = l - ( 1461 * i ) / 4 + 31;
00117     j = ( 80 * l ) / 2447;
00118     *day = l - ( 2447 * j ) / 80;
00119     l = j / 11;
00120     *month = j + 2 - ( 12 * l );
00121     *year = 100 * ( n - 49 ) + i + l;
00122 
00123 
00124   }
00125 
00126 
00127 
00128   void
00129   GregorianCalendarConverter::calendar2jday(eyedblib::int32 * julian, const eyedblib::int32 year, const eyedblib::int16 month, const eyedblib::int16 day)
00130   {
00131     // check the year
00132     if(year < -4713)
00133       {
00134         *julian=-1;
00135         return;
00136       }
00137   
00138 
00139     // run the conversion algorithm
00140   
00141     *julian = ( 1461 * ( year + 4800 + ( month - 14 ) / 12 ) ) / 4 + 
00142       ( 367 * ( month - 2 - 12 * ( ( month - 14 ) / 12 ) ) ) / 12 - 
00143       ( 3 * ( ( year + 4900 + ( month - 14 ) / 12 ) / 100 ) ) / 4 + day - 32075;
00144  
00145 
00146     // check the value
00147     if( *julian < 0 )
00148       {
00149         *julian = -1;
00150       }
00151    
00152    
00153   }
00154 
00155 
00156 
00157   eyedblib::int16
00158   GregorianCalendarConverter::jday2day_of_year(const eyedblib::int32 julian)
00159   {  
00160     jday2calendar(julian, &(this->tmp_year), 0, 0);
00161     eyedblib::int32 first_day_julian = 0;
00162     calendar2jday(&first_day_julian, tmp_year, 1, 0);
00163   
00164     return julian - first_day_julian;
00165   }
00166 
00167   Bool
00168   GregorianCalendarConverter::jday2leap_year(const eyedblib::int32 julian)
00169   {
00170     jday2calendar(julian, &(this->tmp_year), 0, 0);
00171  
00172 
00173     if( !(tmp_year % 4) 
00174         && ( tmp_year % 100
00175              || !(tmp_year % 400) ) )
00176       {
00177         return True;
00178       }
00179     else
00180       {
00181         return False;
00182       }
00183   }
00184 
00185 
00186 
00187   Weekday::Type
00188   GregorianCalendarConverter::jday2weekday(const eyedblib::int32 julian)
00189   {
00190     return (Weekday::Type)((julian + 1) % 7);
00191   }
00192 
00193   eyedblib::int32
00194   GregorianCalendarConverter::ascii2jday(const char * date)
00195   {
00196     //
00197     // Parsing
00198     //
00199 
00200     // check the length
00201     int len = strlen(date);
00202     if(len > 13 
00203        || len < 5)
00204       {
00205         return -1;
00206       }
00207 
00208     strcpy(string_date, date);
00209 
00210 
00211     // break the string between year and month
00212     // by paying attention to the leading '-' that would appear
00213     // if the year was < 0
00214     strtok(string_date + 1, "-");
00215                                             
00216     // get month and day strings
00217     char * s_month = strtok(0, "-");
00218     char * s_day = strtok(0, "-");
00219 
00220 
00221     // check the tokens
00222     if(s_month == 0
00223        || s_day == 0
00224        || (isdigit(string_date[0]) == 0 && string_date[0] != '-')
00225        || isdigit(s_month[0]) == 0
00226        || isdigit(s_day[0]) == 0 )
00227       {
00228         return -1;
00229       }
00230   
00231 
00232     //
00233     // Convert strings into numerical values
00234     //
00235     tmp_year = atol(string_date);
00236     tmp_month = atoi(s_month);
00237     tmp_day = atoi(s_day);
00238 
00239 
00240     //
00241     // Computes the julian day
00242     //
00243     eyedblib::int32 julian = 0;
00244     calendar2jday(&julian, tmp_year, tmp_month, tmp_day);
00245 
00246 
00247     return julian;
00248   }
00249 
00250   char *
00251   GregorianCalendarConverter::jday2ascii(const eyedblib::int32 julian)
00252   {
00253  
00254     jday2calendar(julian, &tmp_year, &tmp_month, &tmp_day);
00255 
00256 
00257     char * return_value = new char[MAX_STRING_DATE];
00258     sprintf(return_value, "%ld-%.2d-%.2d", tmp_year, tmp_month, tmp_day);
00259 
00260     return return_value;
00261   }
00262 
00263   eyedblib::int32
00264   GregorianCalendarConverter::current_date()
00265   {
00266     struct timeval now;
00267     gettimeofday(&now, 0);
00268 
00269     eyedblib::int32 julian = JULIAN_19700101 + (now.tv_sec / (3600*24));
00270 
00271     return julian;
00272   }
00273 }

Generated on Mon Dec 22 18:15:55 2008 for eyedb by  doxygen 1.5.3