Jump to content
View in the app

A better way to browse. Learn more.

FMForums.com

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Refactoring a Holiday Work Week function

Featured Replies

Have a system that creates schedule inspections for months in advance.

Trying to refactor my functions and calculations to make it recursive so each date that is shifted to avoid holiday and off days are also tested to make sure that the suggested date does not fall on a holiday or off day. 

here is my CF that I am using to test for holiday.

/*
 * =====================================
 * BusinessHolidays ( theDate ; return  )
 *
 * RETURNS:
 *		A ¶-delimited list of the dates or names of observed holidays in the year
 *
 * PARAMETERS:
 *		theDate for extracting the year
 *		return 0-8 for dates for names minor major
 *
 * DEPENDENCIES: ValuePosition
 *
 * NOTES:
 *		This version of this function includes observed U.S. federal holidays.
 *		It should be modified to include any holidays observed by the users of
 *		each particular system.
 *
 * HISTORY:
 *		CREATED on 2011-10-18 by Jeremy Bante http://scr.im/jbante.
 *		MODIFIED on 2016-08-19 by Stephen Dolenski
 * =====================================
*/


Let ( [

theYear = Case ( IsValid ( GetAsDate (theDate) ) ; Year ( theDate ) ; GetAsNumber ( theDate ) ) ; 

@nyd = "New Years Day" ;
nyd = Date ( 1 ; 1 ; theYear ) ;

@mlk = "Martin Luther King, Jr. Day" ; // (3rd Monday in January)
mlk = Date ( 1 ; 15 ; theYear )	// earliest possible date
      + Choose ( DayOfWeek ( Date ( 1 ; 1 ; theYear ) ) - 1;
      1 ; 0 ; 6 ; 5 ; 4 ; 3 ; 2 );	// adjust for day of week of month start

@pd = "President's Day"; // (3rd Monday in February)
pd = Date ( 2 ; 15 ; theYear )	// earliest possible date
      + Choose ( DayOfWeek ( Date ( 2 ; 1 ; theYear ) ) - 1;
      1 ; 0 ; 6 ; 5 ; 4 ; 3 ; 2 );	// adjust for day of week of month start

@md = "Memorial Day"; // (last Monday in May)
md = Date ( 5 ; 25 ; theYear )	// earliest possible date
      + Choose ( DayOfWeek ( Date ( 5 ; 31 ; theYear ) ) - 1;
      0 ; 6 ; 5 ; 4 ; 3 ; 2 ; 1 );	// adjust for day of week of month end

@id = "Independence Day"; // (4 July)
id = Date ( 7 ; 4 ; theYear ) ;

@ld = "Labor Day"; // (1st Monday in September)
ld = Date ( 9 ; 1 ; theYear ) // earliest possible date
	+ Choose ( DayOfWeek ( Date ( 9 ; 1 ; theYear ) ) - 1;
		1 ; 0 ; 6 ; 5 ; 4 ; 3 ; 2 );	// adjust for day of week of month start

@cd = "Columbus Day" ; // (2nd Monday in October)
cd = Date ( 10 ; 8 ; theYear )	// earliest possible date
      + Choose ( DayOfWeek ( Date ( 10 ; 1 ; theYear ) ) - 1;
      1 ; 0 ; 6 ; 5 ; 4 ; 3 ; 2 );	// adjust for day of week of month start

@vd = "Veterans Day" ; // (11 November)
vd = Date ( 11 ; 11 ; theYear );			

@td = "Thanksgiving Day" ; // (4th Thursday in November)
td = Date ( 11 ; 22 ; theYear )	// earliest possible date
      + Choose ( DayOfWeek ( Date ( 11 ; 1 ; theYear ) ) - 1;
      4 ; 3 ; 2 ; 1 ; 0 ; 6 ; 5	); // adjust for day of week of month start

@xe = "Christmas Eve" ; // (24 December)
xe =  Date ( 12 ; 24 ; theYear ) ;

@xd = "Christmas Day" ; // (25 December)
xd = Date ( 12 ; 25 ; theYear );
        
@nye = "New Years Eve" ; // (Last Day of Year)        
nye = Date ( 12 ; 31 ; theYear );

//LIST OF HOLIDAY DATES
major = List ( nyd ; id ; td ; xe ; xd ; nye ) ;
minor = List ( mlk ; pd ; md ; ld ; cd ; vd ) ;
dates = List ( nyd ; mlk ; pd ; md ; id ; ld ; cd ; vd ; td ; xe ; xd ; nye ) ; 

//LIST OF HOLIDYAY NAMES
holidayMajor = List ( @nyd ; @id ; @td ; @xe ; @xd ; @nye );
holidayMinor = List ( @mlk ; @pd ; @md ; @ld ; @cd ; @vd );
holiday = List ( @nyd ; @mlk ; @pd ; @md ; @id ; @ld ; @cd ; @vd ; @td ; @xe ; @xd ; @nye ) ; 


//RETURN HOLIDAY
~valueReplaced = Substitute ( ¶& dates &¶ ; ¶& theDate &¶ ; "¶•¶" ) ;
~value = Position (
		Substitute ( Filter ( ~valueReplaced ; "•¶" );
		[ ¶ ; "|" ] );
	"•" ; 1 ; 1 ) - 1 ;

name = GetValue ( holiday  ; ~value  ) ;

hCount = Choose ( Month ( theDate ) ; 0 ; 2 ; 1 ; 0 ; 0 ; 1 ; 0 ; 1 ; 0 ; 1 ; 1 ; 2 ; 3 )


];

Choose ( return ; dates ; holiday ; name ; hCount ; minor; holidayMinor; major; holidayMajor ) 

)

Here is my function for avoiding holidays and Friday's & Saturday's

/*
 * =====================================
 * HolidayShift ( theDate )
 *
 * RETURNS:
 *		The next workday not holiday, friday, saturday
 *
 * PARAMETERS:
 *		theDate
 *
 * DEPENDENCIES: 
 *       BusinessHolidays (theDate ; return)
 *
 * NOTES:
 *		
 *
 * HISTORY:
 *		MODIFIED on 2016-08-19 by Stephen Dolenski
 * =====================================
*/

Let ( [

@date= GetAsDate ( theDate ) ; 

@shift = @date  + not IsEmpty ( BusinessHolidays ( @date ; 2 ) ) ; 

@weekend = @shift + Case( DayOfWeek ( @shift ) = 6 ; 2 ; DayOfWeek ( @shift  ) = 7 ; 1  ) 

];

@weekend + not  IsEmpty ( BusinessHolidays ( @weekend  ; 2 ) )

)

This is the field that should return the results, the only extra thing is that we push forward all inspections that are tagged for AM to the next day (non holiday)  if they fall on Sunday.

Let ( [

a = HolidayShift ( Date ( Month(schedule::ScheduleDate) ; PlanDay ; Year ( schedule::ScheduleDate) ) ) ;

b = HolidayShift ( a ) ;

c = Case ( DayOfWeek ( b ) = 1 and AM_PM = "AM" ;  HolidayShift ( b + 1 ) ; b ) 


];

HolidayShift ( c )

)

I keep having to test each proposed date to make sure that is a real work day, thinking there is a better way to optimize this.

46 minutes ago, Ocean West said:

keep having to test each proposed date to make sure that is a real work day, thinking there is a better way to optimize this.

I don't think so. There is no way to calculate if a date is a holiday without testing it against all possible holidays.

 

52 minutes ago, Ocean West said:

not IsEmpty ( BusinessHolidays ( @date ; 2 ) ) ;

That doesn't look right. Doesn't the function return a list of holidays in the year of @date? That list will never be empty.

  • Author

The first function will return the following: 

0 return list of major and minor dates
1 return list of major and minor holiday names
2 the name of the holiday if the date matches
3 count of holidays in the month
4 list of minor holiday dates
5 list of minor holiday names
6 list of major holiday dates
7 list of major holiday names

 

Quote

 

not IsEmpty ( BusinessHolidays ( @date ; 2 ) ) ;

 

that would return a 1 if it is a holiday 

13 minutes ago, Ocean West said:

The first function will return the following: 

...
2 the name of the holiday if the date matches

<shrug> That's not what it says on the label.

Perhaps you should call the function only once, then test each date against the returned list. But you would have to mind the end of a year.

Create an account or sign in to comment

Important Information

By using this site, you agree to our Terms of Use.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.