## Tool for determining the calendar day

• Post author:
• Post category:NL / Siemens PLC

Bij onze vrienden van Siemens kun je deze downloaden. Maar wel pas nadat je betaald hebt ðŸ™„ (CWD_EU) Dus heb ik ‘m zelf maar geschreven in SCL.

[php]
FUNCTION FC370_DAYOFYEAR : INT
TITLE= ‘FC370_DAYOFYEAR’
NAME : DAYOFYR
FAMILY : PROCESS
AUTHOR : VMI_JFO
VERSION : ‘1.0’ //Jfo – 29 juni 2011: This function calculates the number of the day of the year.
// This will generate 1-365 for normal years, and 1-366 for leap years.
// NOTE: this will work until year 2100! Year 2100, 2200, 2300… are NOT leap years!
VAR_INPUT
END_VAR

VAR_TEMP
Err_ReadDate : INT; // error code return

tmpDATE : DT; // time structure
current_DT AT tmpDATE: ARRAY[1..8] OF BYTE; // array for access to time structures

zdn : INT; // help variable
year : INT; // year, format: ?? (19XX – 20XX)
num_of_month : INT; // number of month, jan -1, feb -2,…
day_of_month : INT; // no comments ðŸ™‚
day_of_week : INT; // !!! sun -1, mon -2, tus -3,…, .

days : ARRAY[1..12] OF INT; // array with number of days of all months

i : INT;
numberofdays : INT;

result_INT : INT;
result_REAL : REAL;
END_VAR

BEGIN

year := WORD_TO_INT(SHR(IN:=current_DT[1],N:=4))*10 + WORD_TO_INT(current_DT[1] AND 16#0F); // calculation of year
num_of_month := WORD_TO_INT(SHR(IN:=current_DT[2],N:=4))*10 + WORD_TO_INT(current_DT[2] AND 16#0F); // calculation numb of month
day_of_month := WORD_TO_INT(SHR(IN:=current_DT[3],N:=4))*10 + WORD_TO_INT(current_DT[3] AND 16#0F); // calculation of day
day_of_week := WORD_TO_INT(current_DT[8] AND 16#0F); // calculation day of week

//—————————————————————————
// Fill in the number of days of the months
//—————————————————————————
days[1] := 31; //jan
days[2] := 28; //feb (note: leap year day will be added further…)
days[3] := 31; //mrt
days[4] := 30; //apr
days[5] := 31; //may
days[6] := 30; //jun
days[7] := 31; //jul
days[8] := 31; //aug
days[9] := 30; //sep
days[10] := 31; //oct
days[11] := 30; //nov
days[12] := 31; //dec

//—————————————————————————
// Leap year? If it is a leap year then we have to add 1 extra day for month february.
//—————————————————————————
result_INT := year / 4;
result_REAL := INT_TO_REAL(year) / 4;

IF result_REAL – INT_TO_REAL(result_INT) = 0 THEN
days[2] := days[2] + 1; //feb
END_IF;

//—————————————————————————
// Calculate number days of previous months.
//—————————————————————————
numberofdays := 0;
FOR i:= 1 TO num_of_month – 1 BY 1 DO
numberofdays := numberofdays + days[i];
END_FOR;

//—————————————————————————
// Calculate number days of current months.
//—————————————————————————
numberofdays := numberofdays + day_of_month;

//—————————————————————————
// Move result to the output.
//—————————————————————————
FC370_DAYOFYEAR := numberofdays;
END_FUNCTION
[/php]

From Siemens:

[php]
FUNCTION CWD_EU : INT

(*
F U N C T I O N C L N D R _ W E E K _ D A Y ( E U )
=================================================================
This function calculates the calendar week for…

– the date specified in input parameter "Date_in" (format: DATE)
if "CPU_clock" = FALSE.

– the current CPU date if "CPU_clock" = TRUE.
(Though "Date_in" is not used in this case, is has to be fed.
with any value)

The calendar week is written to the output parameter "week"
(format: INT). The calendar day is written to the output parameter
"day" (format: INT). The week number is calculated subject to
DIN 1355 / ISO 8601. Week no. 1 is the first week, which includes
at least four days of the new year. The beginning of a week is
always Monday. The function can be used from year 1991 to 2089.

Faults:
Faults are monitored by means of the return value "CWD_EU"
respektively "RET_VAL".
– No error: 0000H
– If input "CPU_clock" = FALSE:
8001H: "Date_in" out of 1991-01-01…2089-12-31
– If input "CPU_clock" = TRUE:

revision history:
01.01.2009 Version 1.1:
New querry for checking calendar week:
When variable ‘tValue’ is 53 than it has to be checked,
if ‘int_Date’ is in week 53 of this year or in the first
week of the following year.
*)

TITLE= ‘Calendar Week/Day (EU)’
AUTHOR: Hall
FAMILY: TIME_FCT
NAME: CWD_EU
VERSION: ‘1.1’

VAR_INPUT
CPU_clock : BOOL;
Date_in : DATE;
END_VAR

VAR_OUTPUT
week : INT;
day : INT;
END_VAR

VAR_TEMP
CPU_DT : DATE_AND_TIME;
TOD_0 : TIME_OF_DAY;
DT_ref : DATE_AND_TIME;
DT_ref_bytes AT DT_ref : ARRAY[0..7] OF BYTE;
//DT_ref_bytes[0] Year,
//DT_ref_bytes[1] Month,
//DT_ref_bytes[2] Day,
//DT_ref_bytes[3] Hour,
//DT_ref_bytes[4] Minute,
//DT_ref_bytes[5] Second,
//DT_ref_bytes[6] Msec,
//DT_ref_bytes[7] Weekday 1 … 7 (1 = Sunday)
int_Date : DATE;
Date_1Jan : DATE;
weekday_1Jan : INT;
weekday_31Dec : INT;
weekday_1Jan_prevY : INT;
weekday_31Dec_prevY : INT;
day_corr : INT;
tValue : INT;
END_VAR

BEGIN

//For date, use input parameter "Date_in" or CPU clock.
IF CPU_clock
THEN
CWD_EU := READ_CLK(CDT := CPU_DT); //SFC 1
//Leave program, if error in return value of READ_CLK, otherwise use CPU date and go on.
IF CWD_EU <> 0
THEN RETURN;
ELSE int_Date := DT_DATE(CPU_DT); //FC 6 IEC functions
END_IF;
ELSE
//Leave program, if "Date_in" is out of limits, otherwise use "Date_in" and go on.
//365 = 1991-01-01; 36524 = 2089-12-31
IF DATE_TO_DINT(Date_in) < 365 OR DATE_TO_DINT(Date_in) > 36524
THEN
CWD_EU := INT#16#8001;
RETURN;
ELSE
CWD_EU := 0;
int_DATE := Date_in;
END_IF;
END_IF;

//Date of January 1st in the current year in format DATE
TOD_0 := TOD#00:00:00;
DT_ref := D_TOD_DT(IN1:=int_Date, IN2:=TOD_0); //FC 3 IEC functions
DT_ref_bytes[1] := 1;
DT_ref_bytes[2] := 1;
Date_1Jan := DT_DATE(DT_ref); //FC 6 IEC functions

//Number of days in the current year up to "int_Date"
day := DINT_TO_INT(DATE_TO_DINT(int_Date) – DATE_TO_DINT(Date_1Jan)) + 1;

//Day of week of January, 1st in the current year
weekday_1Jan := DT_DAY(DT_ref); //FC 7 IEC functions

//Correction of numer of days regarding the weekday on January 1st
CASE weekday_1Jan OF
1: day_corr := day -2; //Sunday
2: day_corr := day -1; //Monday
3: day_corr := day ; //Tuesday
4: day_corr := day +1; //Wednesday
5: day_corr := day +2; //Thursday
6: day_corr := day -4; //Friday
7: day_corr := day -3; //Saturday
END_CASE;

//With negative "day_corr", take last week number of last year.
IF day_corr < 0
THEN
//Predecessor of year ’00’ is ’99’; otherwise it’s current year minus 1
IF DT_ref_bytes[0] = B#16#00
THEN DT_ref_bytes[0] := B#16#99;
ELSE DT_ref_bytes[0] := WORD_TO_BYTE(INT_TO_BCD(BCD_TO_INT(DT_ref_bytes[0]) – 1));
END_IF;

//Weekdays of Jan 1st and Dec 31th of precious year
weekday_1Jan_prevY := DT_DAY(DT_ref); //FC 7 IEC functions
DT_ref_bytes[1] := B#16#12;
DT_ref_bytes[2] := B#16#31;
weekday_31Dec_prevY := DT_DAY(DT_ref); //FC 7 IEC functions

//Only if one of the days Jan 1st or Dec 31th of the previous year
//is a Thursday, the current day is in week 53 of the previous year,
//otherwise in week 52.
IF weekday_1Jan_prevY = 5 OR weekday_31Dec_prevY = 5
THEN week := 53;
ELSE week := 52;
END_IF;

ELSE
//With positive "day_corr", take "day_corr" for calculating the calendar week.
tValue := day_corr/7 + 1;

IF (tValue = 53) THEN
//Only if one of the days Jan 1st or Dec 31th is a Thursday,
//the day is in week 53 of the current year, otherwise in week 1 of the following year.
DT_ref_bytes[1] := B#16#12;
DT_ref_bytes[2] := B#16#31;
weekday_31Dec := DT_DAY(DT_ref);
IF(weekday_1Jan = 5 OR weekday_31Dec = 5) THEN
week := 53;
ELSE
week := 1;
END_IF;
ELSE
week := tValue;
END_IF;
END_IF;

END_FUNCTION
[/php]

```and

```

[php]
FUNCTION CWD_US : INT

(*
F U N C T I O N C L N D R _ W E E K _ D A Y ( U S )
=================================================================
This function calculates the calender week and calender day for…

– the date specified in input parameter "Date_in" (format: DATE)
if "CPU_clock" = FALSE.

– the current CPU date if "CPU_clock" = TRUE.
(Though "Date_in" is not used in this case, is has to be fed.
with any value)

The calendar week is written to the output parameter "week"
(format: INT). The calendar day is written to the output parameter
"day" (format: INT). The week number is calculated subject to US
use and MS Excel. It is always week no. 1 which includes January
1st. First and last calender week of the year need not to have seven
days. The beginning of a week is always Sunday. The function can be
used from year 1990 to 2089.

Faults:
Faults are monitored by means of the return value "CWD_US"
respektively "RET_VAL".
– No error: 0000H
– If input "CPU_clock" = FALSE:
8001H: "Date_in" out of 1990-01-01…2089-12-31
– If input "CPU_clock" = TRUE:
*)

TITLE= ‘Calendar Week/Day (US)’
AUTHOR: Hall
FAMILY: TIME_FCT
NAME: CWD_US
VERSION: ‘1.0’

VAR_INPUT
CPU_clock : BOOL;
Date_in : DATE;
END_VAR

VAR_OUTPUT
week : INT;
day : INT;
END_VAR

VAR_TEMP
CPU_DT : DATE_AND_TIME;
TOD_0 : TIME_OF_DAY;
DT_ref : DATE_AND_TIME;
DT_ref_bytes AT DT_ref : ARRAY[0..7] OF BYTE;
//DT_ref_bytes[0] Year,
//DT_ref_bytes[1] Month,
//DT_ref_bytes[2] Day,
//DT_ref_bytes[3] Hour,
//DT_ref_bytes[4] Minute,
//DT_ref_bytes[5] Second,
//DT_ref_bytes[6] Msec,
//DT_ref_bytes[7] Weekday 1 … 7 (1 = Sunday)
int_Date : DATE;
Date_1Jan : DATE;
weekday_1Jan : INT;
day_corr : INT;
END_VAR

BEGIN

//For date, use input parameter "Date_in" or CPU clock.
IF CPU_clock
THEN
CWD_US := READ_CLK(CDT := CPU_DT); //SFC 1
//Leave program, if error in return value of READ_CLK, otherwise use CPU date and go on.
IF CWD_US <> 0
THEN RETURN;
ELSE int_Date := DT_DATE(CPU_DT); //FC 6 IEC functions
END_IF;
ELSE
//Leave program, if "Date_in" is out of limits, otherwise use "Date_in" and go on.
//0 = 1990-01-01; 36524 = 2089-12-31
IF DATE_TO_DINT(Date_in) < 0 OR DATE_TO_DINT(Date_in) > 36524
THEN
CWD_US := INT#16#8001;
RETURN;
ELSE
CWD_US := 0;
int_DATE := Date_in;
END_IF;
END_IF;

//Date of January 1st in the current year in format DATE
TOD_0 := TOD#00:00:00;
DT_ref := D_TOD_DT(IN1:=int_Date, IN2:=TOD_0); //FC 3 IEC functions
DT_ref_bytes[1] := 1;
DT_ref_bytes[2] := 1;
Date_1Jan := DT_DATE(DT_ref); //FC 6 IEC functions

//Number of days in the current year up to "int_Date"
day := DINT_TO_INT(DATE_TO_DINT(int_Date) – DATE_TO_DINT(Date_1Jan)) + 1;

//Day of week of January, 1st in the current year
weekday_1Jan := DT_DAY(DT_ref); //FC 7 IEC functions

//Correction of numer of days regarding the weekday on January 1st
CASE weekday_1Jan OF
1: day_corr := day -1; //Sunday
2: day_corr := day ; //Monday
3: day_corr := day +1; //Tuesday
4: day_corr := day +2; //Wednesday
5: day_corr := day +3; //Thursday
6: day_corr := day +4; //Friday
7: day_corr := day +5; //Saturday
END_CASE;

//Calculate calendar week.
week := day_corr/7 + 1;

END_FUNCTION
[/php]