FUNCTION "LGF_DTLtoString_ISO" : String
TITLE = LGF_DTLtoString_ISO
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : Siemens_Digital_Industry
FAMILY : LGF
NAME : LGF_DTLtoString_ISO
//Diese Funktion konvertiert ein Datum vom Datentyp DTL in eine Zeichenkette vom Datentyp STRING im internationalen Format (YYYY MM DD ...).
   VAR_INPUT 
      "date" {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;   // Datum zum Konvertieren im Format DTL
      separator : Char;   // Trennzeichen zwischen den Komponenten des ausgegebenen Datums.
   END_VAR

   VAR_TEMP 
      tempString : String;   // Temp string to setup the date string
      tempIndex : DInt;   // Temp iterator for replacing withspaces with '0' in nanosecondstring
   END_VAR

   VAR CONSTANT 
      CONVERT_SIZE_YEAR : USInt := 4;   // Number of character positions for Year
      CONVERT_SIZE_MONTH_DAY_HOUR_MINUTE_SECOND : USInt := 2;   // Number of character positions for Month, Day, Minute and Second
      CONVERT_SIZE_NANOSECOND : USInt := 9;   // Number of character positions for Nanoseconds
      CONVERT_PRECISION : USInt := 0;   // Number of decimal places to convert
      CONVERT_FORMAT_TO_STRING : Word := 16#0000;   // Output format of the characters
      CONVERT_START_POSITION_YEAR : UInt := 1;   // Character starting in string at which position the result is written.
      CONVERT_START_POSITION_MONTH : UInt := 6;   // Character starting in string at which position the result is written.
      CONVERT_START_POSITION_DAY : UInt := 9;   // Character starting in string at which position the result is written.
      CONVERT_START_POSITION_HOUR : UInt := 12;   // Character starting in string at which position the result is written.
      CONVERT_START_POSITION_MINUTE : UInt := 15;   // Character starting in string at which position the result is written.
      CONVERT_START_POSITION_SECOND : UInt := 18;   // Character starting in string at which position the result is written.
      CONVERT_START_POSITION_NANOSECOND : UInt := 21;   // Character starting in string at which position the result is written.
      SEPARATOR_POSITION_YEAR_MONTH : UInt := 5;   // Character starting in string at which position the result is written.
      SEPARATOR_POSITION_MONTH_DAY : UInt := 8;   // Character starting in string at which position the result is written.
      SEPARATOR_POSITION_HOUR_MINUTE : UInt := 14;   // Character starting in string at which position the result is written.
      SEPARATOR_POSITION_MINUTE_SECOND : UInt := 17;   // Character starting in string at which position the result is written.
      SEPARATOR_POSITION_SECOND_NANOSECOND : UInt := 20;   // Character starting in string at which position the result is written.
      SEPARATOR_NANOSECOND : Char := '.';   // Seperator for Nanosecond
      SEPARATOR_TIME : Char := '_';   // Seperator for Time
      SEPARATOR_DATE : Char := '-';   // Default separator for Date
      REPLACE_NANOSECOND_COUNT : DInt := 8;   // Number of Nonosecond characters to be checked for replacing withspaces wit '0'
   END_VAR


BEGIN
	REGION BLOCK INFO HEADER
	  //===============================================================================
	  // SIEMENS AG / (c)Copyright 2019
	  //-------------------------------------------------------------------------------
	  // Title:            LGF_DTLtoString_ISO
	  // Comment/Function: This function converts a date of data type DTL into a character string of data type STRING in international format (YYYY MM DD…).
	  // Library/Family:   LGF (Library General Functions)
	  // Author:           Siemens Digital Industry Support
	  // Tested with:      S7-PLCSIM Advanced V2.0 SP1
	  // Engineering:      TIA Portal V15.1
	  // Restrictions:     ENO mechanism is not used, no error handling
	  // Requirements:     PLC (S7-1200 / S7-1500)
	  //-------------------------------------------------------------------------------
	  // Change log table:
	  // Version  | Date       | Expert in charge       | Changes applied
	  //----------|------------|------------------------|------------------------------
	  // 01.00.00 | 15.06.2016 | Siemens Industry Online Support
	  //                         First released version
	  // 01.00.01 | 02.01.2017 | Siemens Industry Online Support
	  //                         Upgrade: TIA Portal V14 Update 1
	  // 01.00.02 | 17.08.2018 | Siemens Industry Online Support
	  //                         Upgrade: TIA V15 Update 2
	  // 01.00.03 | 23.11.2018 | Siemens Industry Online Support
	  //                         Upgrade: TIA V15.1
	  // 01.00.04 | 17.07.2019 | Simatic Systems Support
	  //                         Bugfix - nanosecond precision and '0' filling
	  // 01.00.05 | 18.07.2019 | Simatic Systems Support
	  //                         Renamed from "LGF_DTLtoString" to "LGF_DTLtoString_ISO"
	  //                         Split into two blocks, removed "format" input
	  // 03.00.00 | 23.04.2020 | Simatic Systems Support | Set version to V3.0.0
	  //                         Harmonize the version of the whole library
	  // 03.00.01 | 23.02.2021 | Simatic Systems Support
	  //                         Insert documentation
	  //=============================================================================
	END_REGION Block info header
	
	REGION DESCRIPTION
	  (/*
	Der Baustein liest ein Datum vom Datentyp DTL ein und konvertiert die einzelnen Komponenten des Datums (Jahr, Monat, Tag, Stunde...) in eine Zeichenkette und gibt diese im internationalen Format aus. Das Trennzeichen zwischen den Komponenten des Datums ist variabel.
	
	##### Internationales Format (ISO 8601):
	
	{.imagePageWidth}
	![LGF_DTLtoString_ISO - Aufbau der Zeichenkette nach ISO 8601](LGF_DTLtoString_ISO.png "LGF_DTLtoString_ISO - Aufbau der Zeichenkette nach ISO 8601")
	
	##### Trennzeichen:
	
	Am Eingangsparameter `separatorDate` geben Sie das Trennzeichen zwischen den Komponenten des Kalenderdatums vor.
	
	##### Beispiel:
	
	* separatorDate = `/` - outString = `2016/03/16…`
	* separatorDate = `-` - outString = `2016-03-16…`
	*/)
	END_REGION DESCRIPTION
	
	REGION INITIALISATION
	  #tempString := '';
	END_REGION
	
	REGION CONVERTER
	  // Set format parameters for output string
	  // International ISO 8601
	  // DTL  | Y| Y| Y| Y| -| M| M| -| D| D|  | H| H| :| M| M| :| S| S| .|NS|NS|NS|NS|NS|NS|NS|NS|NS
	  // -----|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--
	  // Pos  | 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29
	  
	  // Convert "Value" into "String" and place at the right position
	  VAL_STRG(FORMAT := #CONVERT_FORMAT_TO_STRING,
	           IN     := #date.YEAR,
	           P      := #CONVERT_START_POSITION_YEAR,
	           PREC   := #CONVERT_PRECISION,
	           SIZE   := #CONVERT_SIZE_YEAR,
	           OUT    => #tempString);    // DTL YEAR --> String --> #tempPosYear
	  
	  VAL_STRG(FORMAT := #CONVERT_FORMAT_TO_STRING,
	           IN     := #date.MONTH,
	           P      := #CONVERT_START_POSITION_MONTH,
	           PREC   := #CONVERT_PRECISION,
	           SIZE   := #CONVERT_SIZE_MONTH_DAY_HOUR_MINUTE_SECOND,
	           OUT    => #tempString);     // DTL MONTH --> String --> #tempPosMonth
	  
	  VAL_STRG(FORMAT := #CONVERT_FORMAT_TO_STRING,
	           IN     := #date.DAY,
	           P      := #CONVERT_START_POSITION_DAY,
	           PREC   := #CONVERT_PRECISION,
	           SIZE   := #CONVERT_SIZE_MONTH_DAY_HOUR_MINUTE_SECOND,
	           OUT    => #tempString);     // DTL DAY --> String --> #tempPosDay
	  
	  VAL_STRG(FORMAT := #CONVERT_FORMAT_TO_STRING,
	           IN     := #date.HOUR,
	           P      := #CONVERT_START_POSITION_HOUR,
	           PREC   := #CONVERT_PRECISION,
	           SIZE   := #CONVERT_SIZE_MONTH_DAY_HOUR_MINUTE_SECOND,
	           OUT    => #tempString);     // DTL HOUR --> String --> #tempPosHour
	  
	  VAL_STRG(FORMAT := #CONVERT_FORMAT_TO_STRING,
	           IN     := #date.MINUTE,
	           P      := #CONVERT_START_POSITION_MINUTE,
	           PREC   := #CONVERT_PRECISION,
	           SIZE   := #CONVERT_SIZE_MONTH_DAY_HOUR_MINUTE_SECOND,
	           OUT    => #tempString);     // DTL MINUTE --> String --> #tempPosMinute
	  
	  VAL_STRG(FORMAT := #CONVERT_FORMAT_TO_STRING,
	           IN     := #date.SECOND,
	           P      := #CONVERT_START_POSITION_SECOND,
	           PREC   := #CONVERT_PRECISION,
	           SIZE   := #CONVERT_SIZE_MONTH_DAY_HOUR_MINUTE_SECOND,
	           OUT    => #tempString);     // DTL SECOND --> String --> #tempPosSecond
	  
	  VAL_STRG(FORMAT := #CONVERT_FORMAT_TO_STRING,
	           IN     := #date.NANOSECOND,
	           P      := #CONVERT_START_POSITION_NANOSECOND,
	           PREC   := #CONVERT_PRECISION,
	           SIZE   := #CONVERT_SIZE_NANOSECOND,
	           OUT    => #tempString);     // DTL NANOSECOND --> String --> #tempPosNanosecond
	  
	  // Place separators at the right position in the string
	  IF #separator = '' THEN
	    #tempString[#SEPARATOR_POSITION_YEAR_MONTH] := #SEPARATOR_DATE;
	    #tempString[#SEPARATOR_POSITION_MONTH_DAY] := #SEPARATOR_DATE;
	  ELSE
	    #tempString[#SEPARATOR_POSITION_YEAR_MONTH] := #separator;
	    #tempString[#SEPARATOR_POSITION_MONTH_DAY] := #separator;
	  END_IF;
	  #tempString[#SEPARATOR_POSITION_HOUR_MINUTE] := #SEPARATOR_TIME;
	  #tempString[#SEPARATOR_POSITION_MINUTE_SECOND] := #SEPARATOR_TIME;
	  #tempString[#SEPARATOR_POSITION_SECOND_NANOSECOND] := #SEPARATOR_NANOSECOND;
	  
	  // Correcting the string, due to the conversion of a leading "0" value into a "blank".
	  // Replacing of "blank" by "0"
	  IF (#tempString[#CONVERT_START_POSITION_MONTH] = ' ') THEN
	    #tempString[#CONVERT_START_POSITION_MONTH] := '0';
	  END_IF;
	  
	  IF (#tempString[#CONVERT_START_POSITION_DAY] = ' ') THEN
	    #tempString[#CONVERT_START_POSITION_DAY] := '0';
	  END_IF;
	  
	  IF (#tempString[#CONVERT_START_POSITION_HOUR] = ' ') THEN
	    #tempString[#CONVERT_START_POSITION_HOUR] := '0';
	  END_IF;
	  
	  IF (#tempString[#CONVERT_START_POSITION_MINUTE] = ' ') THEN
	    #tempString[#CONVERT_START_POSITION_MINUTE] := '0';
	  END_IF;
	  
	  IF (#tempString[#CONVERT_START_POSITION_SECOND] = ' ') THEN
	    #tempString[#CONVERT_START_POSITION_SECOND] := '0';
	  END_IF;
	  
	  FOR #tempIndex := 0 TO #REPLACE_NANOSECOND_COUNT DO
	    IF (#tempString[UINT_TO_SINT(#CONVERT_START_POSITION_NANOSECOND) + #tempIndex] = ' ') THEN
	      #tempString[UINT_TO_SINT(#CONVERT_START_POSITION_NANOSECOND) + #tempIndex] := '0';
	    ELSE
	      EXIT;
	    END_IF;
	  END_FOR;
	END_REGION
	
	REGION OUTPUTS
	  #LGF_DTLtoString_ISO := #tempString;
	  // no error handling needed
	  ENO := TRUE;
	END_REGION
	
END_FUNCTION

