FUNCTION "fc7_AddSixMonths" : Date
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
dtLast : Date;
END_VAR
VAR_TEMP
DTL1 {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;
myDTL1 AT DTL1 : "myDTL";
DTL2 {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;
myDTL2 AT DTL2 : "myDTL";
END_VAR
BEGIN
#DTL1 := DATE_TO_DTL(IN := #dtLast);
#DTL2 := #DTL1;
#myDTL2.usMonth := #myDTL1.usMonth + 6;
IF #myDTL2.usMonth > 12 THEN
#myDTL2.usMonth := #myDTL2.usMonth - 12;
#myDTL2.uiYear += 1;
END_IF;
#fc7_AddSixMonths := DTL_TO_DATE(IN := #DTL2);
END_FUNCTION
TYPE "myDTL"
VERSION : 0.1
STRUCT
uiYear : UInt;
usMonth : USInt;
usDay : USInt;
usWeekDay : USInt;
usHour : USInt;
usMinute : USInt;
usSecond : USInt;
udNanoSecond : UDInt;
END_STRUCT;
END_TYPE
Honestly, calendar math is super hard. There are so many corner cases: leap years (except the ones that aren't), months with different numbers of days...
I think drbitboy's ideas are solid. Is 6 months-ish good enough? If so, I'd just add 30 days * 6 mo = 180 days (or the 182 or 183 from above) and move on. If not.... check for as many corner cases as you can think of. DTL makes it easy to parse the date/time, but unfortunately it isn't magic, and the PLC doesn't automatically shift everything if the month suddenly becomes 14. It just fails when you try to use the DTL later.