DSN8EUDN

Returns the day of the week (Monday through Sunday) on which a given date in ISO format (YYYY-MM-DD) falls.

 /*********************************************************************
 * Module name = DSN8EUDN (DB2 sample program)                        *
 *                                                                    *
 * DESCRIPTIVE NAME = Query day of the week (UDF)                     *
 *                                                                    *
 *     LICENSED MATERIALS - PROPERTY OF IBM                           *
 *     5675-DB2                                                       *
 *     (C) COPYRIGHT 2000 IBM CORP.  ALL RIGHTS RESERVED.             *
 *                                                                    *
 *     STATUS = VERSION 7                                             *
 *                                                                    *
 * Function: Returns the day of the week (Monday through Sunday) on   *
 *           which a given date in ISO format (YYYY-MM-DD) falls.     *
 *                                                                    *
 *           Example invocation:                                      *
 *            EXEC SQL SET :dayname = DAYNAME( "2000-01-29" );        *
 *            ==> dayname = Tuesday                                   *
 * Notes:                                                             *
 *   Dependencies: Requires IBM C/C++ for OS/390 V1R3 or higher       *
 *                                                                    *
 *   Restrictions: Assumes the Gregorian calendar was adopted in      *
 *                 September, 1752.  Code modifications are required  *
 *                 to handle a different adoption date.               *
 *                                                                    *
 * Module type: C++ program                                           *
 *   Processor: IBM C/C++ for OS/390 V1R3 or higher                   *
 * Module size: See linkedit output                                   *
 *  Attributes: Re-entrant and re-usable                              *
 *                                                                    *
 * Entry Point: DSN8EUDN                                              *
 *     Purpose: See Function                                          *
 *     Linkage: DB2SQL                                                *
 *              Invoked via SQL UDF call                              *
 *                                                                    *
 *       Input: Parameters explicitly passed to this function:        *
 *              - *ISOdateIn   : pointer to a char[11], null-termi-   *
 *                               nated string having a date in ISO    *
 *                               format.                              *
 *              - *niISOdateIn : pointer to a short integer having    *
 *                               the null indicator variable for      *
 *                               *ISOdateIn.                          *
 *              - *fnName      : pointer to a char[138], null-termi-  *
 *                               nated string having the UDF family   *
 *                               name of this function.               *
 *              - *specificName: pointer to a char[129], null-termi-  *
 *                               nated string having the UDF specific *
 *                               name of this function.               *
 *                                                                    *
 *                                                                    *
 *      Output: Parameters explicitly passed by this function:        *
 *              - *dayNameOut  : pointer to a char[10], null-termi-   *
 *                               nated string to receive the dayname  *
 *                               for ISOdateIn.                       *
 *              - *niDayNameOut: pointer to a short integer to re-    *
 *                               ceive the null indicator variable    *
 *                               for *dayNameOut.                     *
 *              - *sqlstate    : pointer to a char[06], null-termi-   *
 *                               nated string to receive the SQLSTATE.*
 *              - *message     : pointer to a char[70], null-termi-   *
 *                               nated string to receive a diagnostic *
 *                               message if one is generated by this  *
 *                               function.                            *
 *                                                                    *
 * Normal Exit: Return Code: SQLSTATE = 00000                         *
 *              - Message: none                                       *
 *                                                                    *
 *  Error Exit: Return Code: SQLSTATE = 38601                         *
 *              - Message: DSN8EUDN Error: No date entered            *
 *              Return Code: SQLSTATE = 38602                         *
 *              - Message: DSN8EUDN Error: Input date not valid       *
 *                                         or not in ISO format"      *
 *                                                                    *
 *    External References:                                            *
 *             - Routines/Services:                                   *
 *               - strftime: Formatted time conversion routine        *
 *                 - from IBM C/C++ for z/OS run-time library         *
 *               - strptime: Date and time conversion routine         *
 *                 - from IBM C/C++ for z/OS run-time library         *
 *             - Data areas       : None                              *
 *             - Control blocks   : None                              *
 *                                                                    *
 *                                                                    *
 *  Pseudocode:                                                       *
 *   DSN8EUDN:                                                        *
 *   - Verify that a date was passed in:                              *
 *     - if *ISOdateIn blank or niISOdateIn is not 0, no date passed: *
 *       - issue SQLSTATE 38601 and a diagnostic message.             *
 *   - Use strptime to validate the entry                             *
 *     - if *ISOdateIn is not a valid ISO date:                       *
 *       - issue SQLSTATE 38602 and a diagnostic message              *
 *   - Parse out the year, month, and day                             *
 *   - Compute the weekday number (0=Sunday, ..., 6=Saturday)         *
 *   - Use strptime and strftime to convert the day number to the     *
 *     full weekday name of the current locale.                       *
 *   End DSN8EUDN                                                     *
 *                                                                    *
 *  Change log:                                                       *
 *  2004-02-25: Rewritten due to demise of IBM Open Class library     *
 *                                                                    *
 *********************************************************************/
 extern "C" void DSN8EUDN              /* Establish linkage          */
 ( char        *ISOdateIn,             /* in: date to look up        */
   char        *dayNameOut,            /* out: ISOdateIn's day name  */
   short int   *niISOdateIn,           /* in: indic var, ISOdateIn   */
   short int   *niDayNameOut,          /* out: indic var, dayNameOut */
   char        *sqlstate,              /* out: SQLSTATE              */
   char        *fnName,                /* in: family name of function*/
   char        *specificName,          /* in: specific name of func  */
   char        *message                /* out: diagnostic message    */
 );
 #pragma linkage(DSN8EUDN,fetchable)   /* Establish linkage          */

 /********************** C library definitions ***********************/
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>

 /***************************** Equates ******************************/
 #define     NULLCHAR     '\0'         /* Null character             */

 #define     MATCH          0          /* Comparison status: Equal   */
 #define     NOT_OK         0          /* Run status indicator: Error*/
 #define     OK             1          /* Run status indicator: Good */

 /*********************** DSN8EUDN functions *************************/

 /********************************************************************/
 /*************************** main routine ***************************/
 /********************************************************************/
 void DSN8EUDN                         /* main routine               */
 ( char        *ISOdateIn,             /* in: date to look up        */
   char        *dayNameOut,            /* out: ISOdateIn's day name  */
   short int   *niISOdateIn,           /* in: indic var, ISOdateIn   */
   short int   *niDayNameOut,          /* out: indic var, dayNameOut */
   char        *sqlstate,              /* out: SQLSTATE              */
   char        *fnName,                /* in: family name of function*/
   char        *specificName,          /* in: specific name of func  */
   char        *message                /* out: diagnostic message    */
 )
 /*********************************************************************
 * Returns the weekday name of the date in ISOdateIn.                 *
 *                                                                    *
 * Assumptions:                                                       *
 * - *ISOdateIn        points to a char[11], null-terminated string   *
 * - *dayNameOut       points to a char[10], null-terminated string   *
 * - *niISOdateIn      points to a short integer                      *
 * - *niDayNameOut     points to a short integer                      *
 * - *sqlstate         points to a char[06], null-terminated string   *
 * - *fnName           points to a char[138], null-terminated string  *
 * - *specificName     points to a char[129], null-terminated string  *
 * - *message          points to a char[70], null-terminated string   *
 *********************************************************************/
 {

   /************************ local variables *************************/
   short int   status = OK;            /* DSN8EUDN run status        */
   struct tm   tmbuff;                 /* buffer for time.h tm struct*/
   char        *rc;                    /* gets strf/ptime return code*/

   char        *tokPtr;                /* string ptr for token parser*/
   char        workStr[11];            /* work copy of ISOdateIn parm*/

   int         yearInt;                /* numeric copy of 4-digit yr */
   char        yearStr[05];            /* string copy of 4-digit year*/

   int         monthInt;               /* numeric copy of month no.  */
   char        monthStr[03];           /* string copy of month no.   */

   int         dayInt;                 /* numeric copy of day no.    */
   char        dayStr[03];             /* string copy of day no.     */

   int         weekDayInt;             /* week day no (0=Sun...6=Sat)*/
   char        weekDayStr[02];         /* string copy of week day no.*/

   char        *isoFormat              /* format of isoDate:         */
               = "%Y-%m-%d";           /* %Y = YYYY, %m = MM, %d = DD*/
   char        *weekDayFormat          /* format of weekday:         */
               = "%w";                 /* %w = weekday               */
   char        *weekDayLongNameFormat  /* format of weekday long name*/
               = "%A";                 /* %A = weekday long name     */

   /*******************************************************************
   * Verify that something has been passed in                         *
   *******************************************************************/
   if( *niISOdateIn != 0 || ( strlen( ISOdateIn ) == 0 ) )
     {
       status = NOT_OK;
       strcpy( message,
               "DSN8EUDN Error: No date entered" );
       strcpy( sqlstate, "38601" );
     }

   /*******************************************************************
   * Verify that the input looks like a date                          *
   *******************************************************************/
   if( status == OK )
     { rc = strptime( ISOdateIn,isoFormat,&tmbuff );
       if( rc == NULL )                /* Unable to convert ISOdateIn*/
         {
           status = NOT_OK;
           strcpy( message,
                   "DSN8EUDN Error: Input date not valid "
                                   "or not in ISO format" );
           strcpy( sqlstate, "38602" );
         }
     }

   /*******************************************************************
   * Parse the 4-digit year, the month no., and day no. from ISOdateIn*
   *******************************************************************/
   if( status == OK )
     { strcpy( workStr,ISOdateIn );

       tokPtr  = strtok( workStr,"-" );
       strcpy( yearStr,tokPtr );
       yearInt  = atoi( yearStr );

       tokPtr  = strtok( NULL,"-" );
       strcpy( monthStr,tokPtr );
       monthInt = atoi( monthStr );

       tokPtr  = strtok( NULL,"-" );
       strcpy( dayStr,tokPtr );
       dayInt   = atoi( dayStr );
     }

   /*******************************************************************
   * Get the weekday name of ISOdateIn                                *
   *******************************************************************/
   if( status == OK )
     { /***************************************************************
       * Leap year allowance: Shift Jan and Feb to end of prev year   *
       ***************************************************************/
       if( monthInt < 3)
         { monthInt += 12;
           yearInt--;
         }

       /***************************************************************
       * Calculate weekday no. with Sunday basis                      *
       ***************************************************************/
       weekDayInt = (   ((13 * monthInt) + 3) / 5  /* xform months   */
                      + dayInt                     /* + days         */
                      + yearInt                    /* + years        */
                      + yearInt / 4                /* + leapyear/4   */
                      - yearInt / 100              /* - leapyear/100 */
                      + yearInt / 400              /* + leapyear/400 */
                      + 1                          /* + Sunday basis */
                    ) % 7;                         /* % days per wk  */

       /***************************************************************
       * adjust for pre-gregorian calendar (September 1752)           *
       ***************************************************************/
       if( (yearInt < 1752) || (yearInt == 1752 && monthInt < 9) )
         { if( weekDayInt > 3 )
             weekDayInt = weekDayInt - 4;
           else
             weekDayInt = weekDayInt + 3;
         }

       /***************************************************************
       * convert day of week from numeric to string                   *
       ***************************************************************/
       sprintf( weekDayStr,"%02d",weekDayInt );

       /***************************************************************
       * Convert day of week from numeric string to day name          *
       ***************************************************************/
       rc = strptime( weekDayStr,weekDayFormat,&tmbuff );
       *rc = strftime( dayNameOut,10,weekDayLongNameFormat,&tmbuff );

     }

   /*******************************************************************
   * If weekday name was obtained, clear the message buffer and sql-  *
   * state, and unset the SQL null indicator for dayNameOut.          *
   *******************************************************************/
   if( status == OK )
     {
       *niDayNameOut = 0;
       message[0] = NULLCHAR;
       strcpy( sqlstate,"00000" );
     }
   /*******************************************************************
   * If errors occurred, clear the dayNameOut buffer and set the SQL  *
   * NULL indicator.  A diagnostic message and the SQLSTATE have been *
   * set where the error was detected.                                *
   *******************************************************************/
   else
     {
       dayNameOut[0] = NULLCHAR;
       *niDayNameOut = -1;
     }

   return;
 }  /* end DSN8EUDN */