Function Date_Services(@Service, @Params) /*********************************************************************************************************************** This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written permission from SRP Computer Solutions, Inc. Name : Date_Services Description : Handler program for all module related services. Notes : The generic parameters should contain all the necessary information to process the services. Often this will be information like the data Record and Key ID. Parameters : Service [in] -- Name of the service being requested Error [out] -- Any errors that were created Param1-10 [in/out] -- Additional request parameter holders Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure Metadata : History : (Date, Initials, Notes) 10/31/17 dmb Original programmer. ***********************************************************************************************************************/ #pragma precomp SRP_PreCompiler $insert LOGICAL $insert SERVICE_SETUP // Self referencing declarations. Declare function Memory_Services, Date_Services, SRP_Math Declare subroutine Memory_Services GoToService else Error_Services('Add', Service : ' is not a valid service request within the ' : ServiceModule : ' module.') end Return Response OR '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Service Parameter Options //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Options BOOLEAN = True$, False$ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Services //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------------------------------------------- // GetNumISOWeeks // // Returns the number of weeks within the indicated year based on the ISO 8601 standards. // (cf. https://en.wikipedia.org/wiki/ISO_week_date) //---------------------------------------------------------------------------------------------------------------------- Service GetNumISOWeeks(Year) ServiceKeyID := '*' : Year NumISOWeeks = Memory_Services('GetValue', ServiceKeyID) If NumISOWeeks EQ '' then If (Year NE '') AND (Num(Year)) then ModCurrent = Mod((Year + Int(Year / 4) - Int(Year / 100) + Int(Year / 400)), 7) YearPrevious = Year - 1 ModPrevious = Mod((YearPrevious + Int(YearPrevious / 4) - Int(YearPrevious / 100) + Int(YearPrevious / 400)), 7) NumISOWeeks = 52 + (If ModCurrent EQ 4 OR ModPrevious EQ 3 then 1 else 0) Memory_Services('SetValue', ServiceKeyID, NumISWeeks) end else Error_Services('Add', 'The Year argument was missing or was not a number in the ' : Service : ' service.') end end Response = NumISOWeeks end service //---------------------------------------------------------------------------------------------------------------------- // GetISOWeekDate // // Returns the ISO formatted week date for the indicated Gregorian date based on the ISO 8601 standards. // (cf. https://en.wikipedia.org/wiki/ISO_week_date) //---------------------------------------------------------------------------------------------------------------------- Service GetISOWeekDate(Date) If Not(Num(Date)) then Date = Iconv(Date, 'D') ServiceKeyID := '*' : Date ISOWeekDate = Memory_Services('GetValue', ServiceKeyID) If ISOWeekDate EQ '' then If Date NE '' then // The ISO week date system places the 4 January in the first week. Using this information, the first day of // the ISO year can be calculated. Year = Field(Oconv(Date, 'D4/'), '/', 3, 1) ; // Format the date and get the calendar year. Jan4 = Iconv('01/04/' : Year, 'D') ; // Compulate the 4 January for this year. Jan4DOW = Mod(Jan4, 7) ; // Get the day of week value (0=Sunday, 6=Saturday). If Jan4DOW EQ 0 then Jan4DOW = 7 ; // Give Sunday a value of 7 rather than 0 for computational purposes. FirstDay = Jan4 - (Jan4DOW - 1) ; // Computes the date of Monday, which is always the first day of the ISO week. // Using the same logic, compute the first day of the previous calendar year. PrevYear = Year - 1 PrevJan4 = Iconv('01/04/' : PrevYear, 'D') PrevJan4DOW = Mod(PrevJan4, 7) If PrevJan4DOW EQ 0 then PrevJan4DOW = 7 PrevFirstDay = PrevJan4 - (PrevJan4DOW - 1) // Again, using the same logic, compute the first day of the next calendar year. NextYear = Year + 1 NextJan4 = Iconv('01/04/' : NextYear, 'D') NextJan4DOW = Mod(NextJan4, 7) If NextJan4DOW EQ 0 then NextJan4DOW = 7 NextFirstDay = NextJan4 - (NextJan4DOW - 1) // Compare the indicated date to see which ISO year it falls within. Begin Case Case Date GE FirstDay AND Date LT NextFirstDay WeekYear = Field(Oconv(FirstDay + 7, 'D4/'), '/', 3, 1) WeekNumber = Fmt(Int((Date - FirstDay) / 7) + 1, 'R(0)#2') Case Date LT FirstDay WeekYear = Field(Oconv(FirstDay - 7, 'D4/'), '/', 3, 1) WeekNumber = Fmt(Int((Date - PrevFirstDay) / 7) + 1, 'R(0)#2') Case Date GE NextFirstDay WeekYear = Field(Oconv(NextFirstDay + 7, 'D4/'), '/', 3, 1) WeekNumber = Fmt(Int((Date - NextFirstDay) / 7) + 1, 'R(0)#2') End Case DOW = Mod(Date, 7) If DOW EQ 0 then DOW = 7 ISOWeekDate = WeekYear : '-W' : WeekNumber : '-' : DOW Memory_Services('SetValue', ServiceKeyID, ISOWeekDate) end else Error_Services('Add', 'The Date argument was missing in the ' : Service : ' service.') end end Response = ISOWeekDate end service //---------------------------------------------------------------------------------------------------------------------- // GetWeekDate // // Returns the week date for the indicated Gregorian date. //---------------------------------------------------------------------------------------------------------------------- Service GetWeekDate(Date) If Not(Num(Date)) then Date = Iconv(Date, 'D') ServiceKeyID := '*' : Date ISOWeekDate = Memory_Services('GetValue', ServiceKeyID) If ISOWeekDate EQ '' then If Date NE '' then // The ISO week date system places the 4 January in the first week. Using this information, the first day of // the ISO year can be calculated. Year = Field(Oconv(Date, 'D4/'), '/', 3, 1) ; // Format the date and get the calendar year. Jan1 = Iconv('01/01/' : Year, 'D') ; // Compulate the 4 January for this year. Jan1DOW = Mod(Jan1, 7) ; // Get the day of week value (0=Sunday, 6=Saturday). If Jan1DOW EQ 0 then Jan1DOW = 7 ; // Give Sunday a value of 7 rather than 0 for computational purposes. FirstDay = Jan1 - (Jan1DOW - 1) ; // Computes the date of Monday, which is always the first day of the ISO week. // Using the same logic, compute the first day of the previous calendar year. PrevYear = Year - 1 PrevJan1 = Iconv('01/01/' : PrevYear, 'D') PrevJan1DOW = Mod(PrevJan1, 7) If PrevJan1DOW EQ 0 then PrevJan1DOW = 7 PrevFirstDay = PrevJan1 - (PrevJan1DOW - 1) // Again, using the same logic, compute the first day of the next calendar year. NextYear = Year + 1 NextJan1 = Iconv('01/01/' : NextYear, 'D') NextJan1DOW = Mod(NextJan1, 7) If NextJan1DOW EQ 0 then NextJan1DOW = 7 NextFirstDay = NextJan1 - (NextJan1DOW - 1) // Compare the indicated date to see which ISO year it falls within. Begin Case Case Date GE FirstDay AND Date LT NextFirstDay WeekYear = Field(Oconv(FirstDay + 7, 'D4/'), '/', 3, 1) WeekNumber = Fmt(Int((Date - FirstDay) / 7) + 1, 'R(0)#2') Case Date LT FirstDay WeekYear = Field(Oconv(FirstDay - 7, 'D4/'), '/', 3, 1) WeekNumber = Fmt(Int((Date - PrevFirstDay) / 7) + 1, 'R(0)#2') Case Date GE NextFirstDay WeekYear = Field(Oconv(NextFirstDay + 7, 'D4/'), '/', 3, 1) WeekNumber = Fmt(Int((Date - NextFirstDay) / 7) + 1, 'R(0)#2') End Case DOW = Mod(Date, 7) If DOW EQ 0 then DOW = 7 ISOWeekDate = WeekYear : '-W' : WeekNumber : '-' : DOW Memory_Services('SetValue', ServiceKeyID, ISOWeekDate) end else Error_Services('Add', 'The Date argument was missing in the ' : Service : ' service.') end end Response = ISOWeekDate end service Service GetWeekNum(InputDate) If Num(InputDate) then InputDate = OConv(InputDate, 'D4/') Year = Field(InputDate, '/', 3, 1) Jan1 = Iconv('01/01/' : Year, 'D') Jan1DOW = Mod(Jan1, 7) // Get Sunday's date FirstSunday = Jan1 - (Jan1DOW + 1) InputDate = IConv(InputDate, 'D') Weeks = SRP_Math('CEILING', ( (InputDate - FirstSunday) / 7) ) Dec31 = IConv('12/31/' : Year, 'D') WeeksInYear = Abs(SRP_Math('FLOOR', ( (Dec31 - FirstSunday) / 7) )) If Weeks GT WeeksInYear then Weeks = Mod(Weeks, WeeksInYear) Response = Fmt(Weeks, 'R(0)#2') end service //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Internal GoSubs ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////