/* * Program Name: date.c * Author: Pat Y. Boens * Copyright (c) 1995 by The DVL Group * ------------------------------------------------------------------------------ * Created: 26 July 1995 at 10:27 * * .............................................................................. * Revision number : 1.0 Last Revised : 26 July 1995 at 10:27 * Description : Date functions. * .............................................................................. * Revision number : 2.0 Last Revised : 21 May 1998 at 23:35 * Description : DAT_easter() public domain by Ed Bernal * .............................................................................. * * Part of FOCUS * * ------------------------------------------------------------------------------ */ #include <windows.h> #include <string.h> #include "pro_ext.h" #include "focus.h" #include "date.h" #include "D:\FOCUS\5.0\FastWrite\functions.h" #define NUMBER_OF_SECONDS_PER_DAY 86400 #ifdef PAPAL // Pope Gregory XIII's decree #define LASTJULDATE 15821004L // last day to use Julian calendar #define LASTJULJDN 2299160L // jdn of same #else // British-American usage #define LASTJULDATE 17520902L // last day to use Julian calendar #define LASTJULJDN 2361221L // jdn of same #endif long ymd_to_jdnl( int y,int m,int d,int julian ); void jdnl_to_ymd( long jdn,int *yy,int *mm,int *dd,int julian ); void easter(int year,int *easter_month, int *easter_day ); void easter(int year,int *easter_month, int *easter_day ) /*-----------------------------------------------------*/ { int a,b,c,e,g,h,i,k,u,x,z; div_t f; /* ** Gauss' famous algorithm (I don't know how or why it works, ** so there's no commenting) */ a = year % 19; f = div(year,100); b = f.quot; c = f.rem; f = div(b,4); z = f.quot; e = f.rem; f = div((8*b + 13),25); g = f.quot; f = div((19*a + b - z - g + 15),30); h = f.rem; f = div((a + 11*h),319); u = f.quot; f = div(c,4); i = f.quot; k = f.rem; f = div((2*e + 2*i - k - h + u + 32),7); x = f.rem; f = div((h-u+x+90),25); *easter_month = f.quot; f = div((h-u+x + *easter_month +19),32); *easter_day = f.rem; } long ymd_to_jdnl( int y,int m,int d,int julian ) /*--------------------------------------------*/ { long jdn; if ( julian < 0 ) /* set Julian flag if auto set */ julian = (((y * 100L) + m) * 100 + d <= LASTJULDATE); if (y < 0) /* adjust BC year */ y++; if (julian) jdn = 367L * y - 7 * (y + 5001L + (m - 9) / 7) / 4 + 275 * m / 9 + d + 1729777L; else jdn = (long)(d - 32076) + 1461L * (y + 4800L + (m - 14) / 12) / 4 + 367 * (m - 2 - (m - 14) / 12 * 12) / 12 - 3 * ((y + 4900L + (m - 14) / 12) / 100) / 4 + 1; /* correction by rdg */ return jdn; } void jdnl_to_ymd( long jdn,int *yy,int *mm,int *dd,int julian ) /*-----------------------------------------------------------*/ { long x,z,m,d,y; long daysPer400Years = 146097L; long fudgedDaysPer4000Years = 1460970L + 31; if (julian < 0) /* set Julian flag if auto set */ julian = (jdn <= LASTJULJDN); x = jdn + 68569L; if ( julian ) { x += 38; daysPer400Years = 146100L; fudgedDaysPer4000Years = 1461000L + 1; } z = 4 * x / daysPer400Years; x = x - (daysPer400Years * z + 3) / 4; y = 4000 * (x + 1) / fudgedDaysPer4000Years; x = x - 1461 * y / 4 + 31; m = 80 * x / 2447; d = x - 2447 * m / 80; x = m / 11; m = m + 2 - 12 * x; y = 100 * (z - 49) + y + x; *yy = (int)y; *mm = (int)m; *dd = (int)d; if (*yy <= 0) /* adjust BC years */ (*yy)--; } FOCUSFNC FW_DAT_easter( XBASE_PARAMETERS ) /*--------------------------------------*/ { int yr,mo,dy; // Julian date to Year-Month-Day jdnl_to_ymd( (long) Parm->p[0].val.ev_real,&yr,&mo,&dy,0 ); // Determine Easter day easter( yr,&mo,&dy ); // Put all this together back as a Julian date Parm->p[0].val.ev_real = ymd_to_jdnl( yr,mo,dy,0 ); // Return the RetVal structure to return a date to FoxPro _RetVal( &Parm->p[0].val ); FOCUSFNCRETURN(); } FOCUSFNC FW_DAT_ymd( XBASE_PARAMETERS ) /*-----------------------------------*/ { int yr, mo, dy; Value val1,val2,val3; _Load( &Parm->p[1].loc,&val1 ); // Put loc in val _Load( &Parm->p[2].loc,&val2 ); // Put loc in val _Load( &Parm->p[3].loc,&val3 ); // Put loc in val jdnl_to_ymd( (long) Parm->p[0].val.ev_real,&yr,&mo,&dy,0 ); // Julian date to Year-Month-Day val1.ev_real = yr; val2.ev_real = mo; val3.ev_real = dy; _Store( &Parm->p[1].loc,&val1 ); _Store( &Parm->p[2].loc,&val2 ); _Store( &Parm->p[3].loc,&val3 ); FOCUSFNCRETURN(); } FOCUSFNC FW_DAT_year( XBASE_PARAMETERS ) /*------------------------------------*/ { int yr, mo, dy; jdnl_to_ymd( (long) Parm->p[0].val.ev_real,&yr,&mo,&dy,0 ); // Julian date to Year-Month-Day _retni( yr ); FOCUSFNCRETURN(); } FOCUSFNC FW_DAT_month( XBASE_PARAMETERS ) /*------------------------------------*/ { int yr, mo, dy; jdnl_to_ymd( (long) Parm->p[0].val.ev_real,&yr,&mo,&dy,0 ); // Julian date to Year-Month-Day _retni( mo ); FOCUSFNCRETURN(); } FOCUSFNC FW_DAT_day( XBASE_PARAMETERS ) /*------------------------------------*/ { int yr, mo, dy; jdnl_to_ymd( (long) Parm->p[0].val.ev_real,&yr,&mo,&dy,0 ); // Julian date to Year-Month-Day _retni( dy ); FOCUSFNCRETURN(); } FOCUSFNC FW_DAT_num( XBASE_PARAMETERS ) /*-----------------------------------*/ { /* Documented */ _retnd( _pard(1) ); // This is in fact returning the julian date !!! FOCUSFNCRETURN(); } FOCUSFNC FW_DAT_boy( XBASE_PARAMETERS ) /*-----------------------------------*/ { int yr, mo, dy; long jdn; jdnl_to_ymd( (long) Parm->p[0].val.ev_real,&yr,&mo,&dy,0 ); // Julian date to Year-Month-Day mo = 1; dy = 1; jdn = ymd_to_jdnl( yr,mo,dy,0 ); // Year-Month-Day to Julian date Parm->p[0].val.ev_real = jdn; _RetVal( &Parm->p[0].val ); FOCUSFNCRETURN(); } FOCUSFNC FW_DAT_bom( XBASE_PARAMETERS ) /*-----------------------------------*/ { int yr, mo, dy; long jdn; jdnl_to_ymd( (long) Parm->p[0].val.ev_real,&yr,&mo,&dy,0 ); // Julian date to Year-Month-Day dy = 1; jdn = ymd_to_jdnl( yr,mo,dy,0 ); // Year-Month-Day to Julian date Parm->p[0].val.ev_real = jdn; _RetVal( &Parm->p[0].val ); FOCUSFNCRETURN(); } FOCUSFNC FW_DAT_eoy( XBASE_PARAMETERS ) /*-----------------------------------*/ { int yr, mo, dy; long jdn; jdnl_to_ymd( (long) Parm->p[0].val.ev_real,&yr,&mo,&dy,0 ); // Julian date to Year-Month-Day mo = 12; dy = 31; jdn = ymd_to_jdnl( yr,mo,dy,0 ); // Year-Month-Day to Julian date Parm->p[0].val.ev_real = jdn; _RetVal( &Parm->p[0].val ); FOCUSFNCRETURN(); } BOOL isleap( long jdn ) /*-------------------*/ { int yr, mo, dy; long jdn1,jdn2; jdnl_to_ymd( jdn,&yr,&mo,&dy,0 ); // Julian date to Year-Month-Day jdn1 = ymd_to_jdnl( yr,1,1,0 ); // Year-Month-Day to Julian date jdn2 = ymd_to_jdnl( yr,12,31,0 ); // Year-Month-Day to Julian date return (( jdn2 - jdn1 ) == 365 ); // A difference of 365 indicates 366 days !!! } FOCUSFNC FW_DAT_isleap( XBASE_PARAMETERS ) /*--------------------------------------*/ { _retl( isleap( (long) Parm->p[0].val.ev_real ) ); FOCUSFNCRETURN(); } FOCUSFNC FW_DAT_eom( XBASE_PARAMETERS ) /*-----------------------------------*/ { int yr, mo, dy; long jdn; enum months { january,february,march,april,may,june,july,august,september,october,november,december }; jdnl_to_ymd( (long) Parm->p[0].val.ev_real,&yr,&mo,&dy,0 ); // Julian date to Year-Month-Day switch ( mo - 1 ) { case january : dy = 31; break; case february : if ( isleap( (long) Parm->p[0].val.ev_real ) ) dy = 29; else dy = 28; break; case march : dy = 31; break; case april : dy = 30; break; case may : dy = 31; break; case june : dy = 30; break; case july : dy = 31; break; case august : dy = 31; break; case september : dy = 30; break; case october : dy = 31; break; case november : dy = 30; break; case december : dy = 31; } jdn = ymd_to_jdnl( yr,mo,dy,0 ); // Year-Month-Day to Julian date Parm->p[0].val.ev_real = jdn; _RetVal( &Parm->p[0].val ); FOCUSFNCRETURN(); } FOCUSFNC FW_DAT_NumberOfDays( XBASE_PARAMETERS ) /*--------------------------------------------*/ { /* Documented */ short n; enum months { january,february,march,april,may,june,july,august,september,october,november,december }; switch ( _parni(1) - 1 ) { case january : n = 31; break; case february : n = 28; break; case march : n = 31; break; case april : n = 30; break; case may : n = 31; break; case june : n = 30; break; case july : n = 31; break; case august : n = 31; break; case september : n = 30; break; case october : n = 31; break; case november : n = 30; break; case december : n = 31; break; default : n = 0; } _retni( n ); FOCUSFNCRETURN(); } FOCUSFNC FW_DAT_DateTime( XBASE_PARAMETERS ) /*----------------------------------------*/ { TCHAR buffer[21]; DateTime( buffer ); _retc( buffer ); FOCUSFNCRETURN(); }