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 */