/******************************************************************************/
// @copyright   Copyright Notification
//   No part may be reproduced except as authorized by written permission.
//   The copyright and the foregoing restriction extend to reproduction in all media.
//   Trademark 2010, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC).
//   All rights reserved.
// @version: IWD_10wk37
// $Date: 2010-08-19 00:48:00 +0200 (Thu, 19 Aug 2010) $
// $Rev: 3727 $
/******************************************************************************/

module SMS_Templates {

import from CommonDefs all;
import from SMS_TypeDefs all;
import from EPS_NAS_TypeDefs all;
import from EPS_NAS_MsgContainers all;
import from EPS_NAS_Constants all;
import from EUTRA_RRC_ASN1_Definitions language "ASN.1:1997" all;
// import from EUTRA_CommonDefs all;

group SMS_Templates_Group {

/* Non-SMS Type Constraints */

template (value) TransactionIdentifier_Type cs_MT_TI0_FromSS :=
{
  tI_Flag := '0'B,
  tI_Value := '000'B
};

template TransactionIdentifier_Type cr_MT_TI0_FromUE :=
{
  tI_Flag := '1'B,
  tI_Value := '000'B
};

template TransactionIdentifier_Type cr_MO_AnyTI_FromUE :=
{
  tI_Flag := '0'B,
  tI_Value := '???'B
};

template (present) TypeOfNumberingPlan cr_TypeOfNumberingPlanAny :=
{
  extBit := ?,
  typeOfNumber := ?,
  numberingPlanId := ?
};

template (value) TypeOfNumberingPlan cs_TypeOfNumberingPlan :=
{
  extBit := '1'B,
  typeOfNumber := '001'B, // international number
  numberingPlanId := '0001'B // ISDN/telephony numbering plan (Rec. E.164/E.163)
};

template (present) TypeOfNumberingPlan cr_TypeOfNumberingPlan :=
{
  extBit := ?,
  typeOfNumber := ?,
  numberingPlanId := ?
};

/* End Non-SMS Type Constraints */

/* SM-CP Type Constraints */
/*
template (omit) CP_UserData_Type cs_CP_UserData (RP_PDU_Type p_RP_PDU,
                                               integer p_Length) :=
{
  spare := omit,
  iei := omit,
  iel := int2oct (p_Length,1), // size of p_RP_PDU in octets, provided by the caller
  rP_PDU := p_RP_PDU
};
*/

template (omit) CP_UserData_Type cs_CP_UserData_DELIVER (octetstring p_Digits):=
{
  spare := omit,
  iei := omit,
  iel := int2oct ((162 + lengthof (p_Digits)), 1), // 162 = 153 + 1 + 5 + 3=size of cs_RP_OriginatorAddress_dl
  rP_PDU := {RP_DATA_dl := cs_RP_DATA_dl_DELIVER (p_Digits)}
};

template (omit) CP_UserData_Type cs_CP_UserData_SUBMIT_REPORT :=
{
  spare := omit,
  iei := omit,
  iel := '0D'O, // the length of RPDU is 13
  rP_PDU := {RP_ACK := cs_RP_ACK_SUBMIT_REPORT}
};
/*
template (present) CP_UserData_Type cr_CP_UserData (RP_PDU_Type p_RP_PDU) :=
{
  spare := omit,
  iei := omit,
  iel := ?,
  rP_PDU := p_RP_PDU
};
*/
template (present) CP_UserData_Type cr_CP_UserData_SUBMIT :=
{
  spare := omit,
  iei := omit,
  iel := ?,
  rP_PDU := {RP_DATA_ul := cr_RP_DATA_ul_SUBMIT}
};

template CP_UserData_Type cr_CP_UserData_DELIVER_REPORT :=
{
  spare := omit,
  iei := omit,
  iel := ?,
  rP_PDU := {RP_ACK := cr_RP_ACK_DELIVER_REPORT}
};

/* End SM-CP Type Constraints */

/* SM-CP PDU Constraints */

template (value) CP_DATA_Type cs_CP_DATA (template (value) TransactionIdentifier_Type p_TransactionIdentifier,
                                          template (omit) CP_UserData_Type p_CP_UserData) :=
{
  transactionIdentifier := p_TransactionIdentifier,
  protocolDiscriminator := tsc_PD_SMS,
  messageType := tsc_MT_CP_DATA,
  cP_UserData := p_CP_UserData
};

template CP_DATA_Type cr_CP_DATA (template TransactionIdentifier_Type p_TransactionIdentifier,
                                  template CP_UserData_Type p_CP_UserData) :=
{
  transactionIdentifier := p_TransactionIdentifier,
  protocolDiscriminator := tsc_PD_SMS,
  messageType := tsc_MT_CP_DATA,
  cP_UserData := p_CP_UserData
};

template (value) CP_ACK_Type cs_CP_ACK (template (value) TransactionIdentifier_Type p_TransactionIdentifier) :=
{
  transactionIdentifier := p_TransactionIdentifier,
  protocolDiscriminator := tsc_PD_SMS,
  messageType := tsc_MT_CP_ACK
};

template CP_ACK_Type cr_CP_ACK (template TransactionIdentifier_Type p_TransactionIdentifier) :=
{
  transactionIdentifier := p_TransactionIdentifier,
  protocolDiscriminator := tsc_PD_SMS,
  messageType := tsc_MT_CP_ACK
};

template (value) CP_ERROR_Type cs_CP_ERROR (TransactionIdentifier_Type p_TransactionIdentifier,
                                            CP_Cause_Type p_CP_Cause) :=
{
  transactionIdentifier := p_TransactionIdentifier,
  protocolDiscriminator := tsc_PD_SMS,
  messageType := tsc_MT_CP_ERROR,
  cP_Cause := p_CP_Cause
};

template CP_ERROR_Type cr_CP_ERROR (template (value) TransactionIdentifier_Type p_TransactionIdentifier,
                                    CP_Cause_Type p_CP_Cause) :=
{
  transactionIdentifier := p_TransactionIdentifier,
  protocolDiscriminator := tsc_PD_SMS,
  messageType := tsc_MT_CP_ERROR,
  cP_Cause := p_CP_Cause
};

template CP_PDU_Type cr_CP_DATA_PDU (template TransactionIdentifier_Type p_TransactionIdentifier,
                                     template CP_UserData_Type p_CP_UserData) :=
{
 CP_DATA := cr_CP_DATA (p_TransactionIdentifier, p_CP_UserData)
};

template (value) CP_PDU_Type cs_CP_DATA_PDU (template (value) TransactionIdentifier_Type p_TransactionIdentifier,
                                     template (value) CP_UserData_Type p_CP_UserData) :=
{
  CP_DATA := cs_CP_DATA (p_TransactionIdentifier, p_CP_UserData)
};

template CP_PDU_Type cr_CP_ACK_PDU (template TransactionIdentifier_Type p_TransactionIdentifier) :=
{
 CP_ACK := cr_CP_ACK (p_TransactionIdentifier)
};

template (value) CP_PDU_Type cs_CP_ACK_PDU (template (value) TransactionIdentifier_Type p_TransactionIdentifier) :=
{
  CP_ACK := cs_CP_ACK (p_TransactionIdentifier)
};

/* End SM-CP PDU Constraints */

/* SM-RP Type Constraints */

template (omit) RP_OriginatorAddress_dl cs_RP_OriginatorAddress_dl :=
{
  spare := omit,
  iei := omit,
  iel := '06'O, // 6 semi-octets
  typeOfNumberingPlan := cs_TypeOfNumberingPlan,
  digits := '001122'O
};

template RP_OriginatorAddress_ul cr_RP_OriginatorAddress_ul :=
{
  spare := omit,
  iei := omit,
  iel := '00'O
};

template RP_DestinationAddress_ul cr_RP_DestinationAddress_ul :=
{
  spare := omit,
  iei := omit,
  iel := ?,
  typeOfNumberingPlan := cr_TypeOfNumberingPlan,
  digits := ?
};
template (omit) RP_DestinationAddress_dl cs_RP_DestinationAddress_dl :=
{
  spare := omit,
  iei := omit,
  iel := '00'O
};
/*
template (omit) RP_UserData cs_RP_UserData (TP_PDU_Type p_TP_PDU) :=
{
  spare := omit,
  iei := omit,
  iel := '05'O,  // to be corrected  !!! ???
  tP_PDU := p_TP_PDU
};
*/
template (omit) RP_UserData cs_RP_UserData_DELIVER (octetstring p_Digits) :=
{
  spare := omit,
  iei := omit,
  iel := int2oct ((153 + lengthof (p_Digits)), 1),
  tP_PDU := {SMS_DELIVER := cs_SMS_DELIVER (p_Digits)}
};

template (omit) RP_UserData cs_RP_UserData_SUBMIT_REPORT :=
{
  spare := tsc_Sparebit,
  iei := tsc_IEI_RP_UserData,
  iel := '0A'O, // the TPDU data length is 10 octets
  tP_PDU := {SMS_SUBMIT_REPORT := cs_SMS_SUBMIT_REPORT}
};
/*
template RP_UserData cr_RP_UserData (TP_PDU_Type p_TP_PDU) :=
{
  spare := omit,
  iei := omit,
  iel := ?,
  tP_PDU := p_TP_PDU
};
*/
template RP_UserData cr_RP_UserData_SUBMIT :=
{
  spare := omit,
  iei := omit,
  iel := ?,
  tP_PDU := {SMS_SUBMIT := cr_SMS_SUBMIT_VPF_REF} // fits with AT command !!
};

template RP_UserData cr_RP_UserData_DELIVER_REPORT :=
{
  spare := tsc_Sparebit,
  iei := tsc_IEI_RP_UserData,
  iel := ?,
  tP_PDU := {SMS_DELIVER_REPORT := cr_SMS_DELIVER_REPORT}
};

/* End SM-RP Type Constraints */

/* SM-RP PDU Constraints */

template (value) RP_DATA_dl_Type cs_RP_DATA_dl_DELIVER (octetstring p_Digits) :=
{
  spare5 := '00000'B,
  rP_MessageTypeIndicator := tsc_MT_RP_DATA_dl,
  rP_MessageReference := int2oct(0,1),
  rP_OriginatorAddress := cs_RP_OriginatorAddress_dl,
  rP_DestinationAddress := cs_RP_DestinationAddress_dl,
  rP_UserData := cs_RP_UserData_DELIVER(p_Digits)
};

template (present) RP_DATA_ul_Type  cr_RP_DATA_ul_SUBMIT :=
{
  spare5 := '00000'B,
  rP_MessageTypeIndicator := tsc_MT_RP_DATA_ul,
  rP_MessageReference := ?,
  rP_OriginatorAddress := cr_RP_OriginatorAddress_ul,
  rP_DestinationAddress := cr_RP_DestinationAddress_ul,
  rP_UserData := cr_RP_UserData_SUBMIT
};

template (value) RP_ACK_Type cs_RP_ACK_SUBMIT_REPORT :=
{
  spare5 := '00000'B,
  rP_MessageTypeIndicator := tsc_MT_RP_ACK_dl,
  rP_MessageReference := int2oct(0,1),
  rP_UserData := cs_RP_UserData_SUBMIT_REPORT
};

template (present) RP_ACK_Type  cr_RP_ACK_DELIVER_REPORT :=
{
  spare5 := '00000'B,
  rP_MessageTypeIndicator := tsc_MT_RP_ACK_ul,
  rP_MessageReference := ?,
  rP_UserData := cr_RP_UserData_DELIVER_REPORT
};

/* End SM-RP PDU Constraints */

/* SM-TP Type Constraints */
template TP_ProtocolIdentifier_Type cr_TP_ProtocolIdentifier :=
{
  pidType := '01'B,
  interworking := '0'B,
  pidValue := '00000'B
};

template (value) TP_ProtocolIdentifier_Type cs_TP_ProtocolIdentifier :=
{
  pidType := '01'B,
  interworking := '0'B,
  pidValue := '00000'B
};

template (value) TP_DataCodingScheme_Type cs_TP_DataCodingScheme :=
{
  codingGroup := '0000'B,
  codeValue := '0000'B
};

template TP_Address_Type cr_TP_AddressAny :=
{
  iel := ?,
  typeOfNumberingPlan := cr_TypeOfNumberingPlanAny,
  digits := *
};

template (value) TP_Address_Type cs_TP_Address (octetstring p_Digits) :=
{
  iel := int2oct(2 * lengthof(p_Digits), 1),
  // length is number of useful semi-octets
  // as p_digits is declared as octetstring the number must be even
  typeOfNumberingPlan := cs_TypeOfNumberingPlan,
  digits := p_Digits
};

template (value) TP_ParameterIndicator_Type cs_TP_ParameterIndicator :=
{
  extBit1 := '0'B,
  spare4 := '0000'B,
  tP_UDL := '0'B,
  tP_DCS := '0'B,
  tP_PID := '1'B
};

/* End SM-TP Type Constraints */

/* SM-TP PDU Constraints */

template (value) SMS_DELIVER_Type cs_SMS_DELIVER (octetstring p_Digits) :=
{
  tP_ReplyPath := '0'B,
  tP_UserDataHeaderIndicator := '0'B,
  tP_StatusReportIndication := '1'B,
  spare2 := '00'B,
  tP_MoreMessagesToSend := '0'B,
  tP_MessageTypeIndicator := tsc_MT_SMS_DELIVER,
  tP_OriginatingAddress := cs_TP_Address (p_Digits),
  tP_ProtocolIdentifier := cs_TP_ProtocolIdentifier,
  tP_DataCodingScheme_Type := cs_TP_DataCodingScheme,
  tP_ServiceCentreTimeStamp := f_GetSC_TimeStamp(),
  tP_UserDataLength := int2oct(160,1),
  tP_UserData := f_IA5_2oct(tsc_Fox)
};

template SMS_DELIVER_REPORT_Type cr_SMS_DELIVER_REPORT :=
{
  spare1 := '0'B,
  tP_UserDataHeaderIndicator  := '0'B,
  spare4 := '0000'B,
  tP_MessageTypeIndicator := tsc_MT_SMS_DELIVER_REPORT,
  tP_FailureCause := omit,
  tP_ParameterIndicator := ?,
  tP_ProtocolIdentifier := cr_TP_ProtocolIdentifier,
  tP_DataCodingScheme_Type := *,
  tP_UserDataLength := *,
  tP_UserData := *
};

template SMS_SUBMIT_Type cr_SMS_SUBMIT :=
{
  tP_ReplyPath := '0'B,
  tP_UserDataHeaderIndicator := '0'B,
  tP_StatusReportRequest := '1'B,
  tP_ValidityPeriodFormat := '??'B,
  tP_RejectDuplicates := '0'B,
  tP_MessageTypeIndicator := tsc_MT_SMS_SUBMIT,
  tP_MessageReference := ?,
  tP_DestinationAddress := cr_TP_AddressAny,
  tP_ProtocolIdentifier := cr_TP_ProtocolIdentifier,
  tP_DataCodingScheme_Type := ?,
  tP_ValidityPeriod  := *,
  tP_UserDataLength := int2oct(160,1),
  tP_UserData := ? // any data will do: 140 octets
};

template SMS_SUBMIT_Type cr_SMS_SUBMIT_VPF_NP :=
{
  tP_ReplyPath := '0'B,
  tP_UserDataHeaderIndicator := '0'B,
  tP_StatusReportRequest := '1'B,
  tP_ValidityPeriodFormat := '00'B,
  tP_RejectDuplicates := '0'B,
  tP_MessageTypeIndicator := tsc_MT_SMS_SUBMIT,
  tP_MessageReference := ?,
  tP_DestinationAddress := cr_TP_AddressAny,
  tP_ProtocolIdentifier := cr_TP_ProtocolIdentifier,
  tP_DataCodingScheme_Type := ?,
  tP_ValidityPeriod  := omit,
  tP_UserDataLength := int2oct(160,1),
  tP_UserData := ? // any data will do: 140 octets
};

template SMS_SUBMIT_Type cr_SMS_SUBMIT_VPF_REF :=
{
  tP_ReplyPath := '0'B,
  tP_UserDataHeaderIndicator := '0'B,
  tP_StatusReportRequest := '1'B,
  tP_ValidityPeriodFormat := '10'B,
  tP_RejectDuplicates := '0'B,
  tP_MessageTypeIndicator := tsc_MT_SMS_SUBMIT,
  tP_MessageReference := ?,
  tP_DestinationAddress := cr_TP_AddressAny,
  tP_ProtocolIdentifier := cr_TP_ProtocolIdentifier,
  tP_DataCodingScheme_Type := ?,
  tP_ValidityPeriod  := ?,
  tP_UserDataLength := int2oct(160,1),
  tP_UserData := ? // any data will do: 140 octets
};

template SMS_SUBMIT_Type cr_SMS_SUBMIT_VPF_ENH :=
{
  tP_ReplyPath := '0'B,
  tP_UserDataHeaderIndicator := '0'B,
  tP_StatusReportRequest := '1'B,
  tP_ValidityPeriodFormat := '01'B,
  tP_RejectDuplicates := '0'B,
  tP_MessageTypeIndicator := tsc_MT_SMS_SUBMIT,
  tP_MessageReference := ?,
  tP_DestinationAddress := cr_TP_AddressAny,
  tP_ProtocolIdentifier := cr_TP_ProtocolIdentifier,
  tP_DataCodingScheme_Type := ?,
  tP_ValidityPeriod  := ?,
  tP_UserDataLength := int2oct(160,1),
  tP_UserData := ? // any data will do: 140 octets
};

template SMS_SUBMIT_Type cr_SMS_SUBMIT_VPF_ABS :=
{
  tP_ReplyPath := '0'B,
  tP_UserDataHeaderIndicator := '0'B,
  tP_StatusReportRequest := '1'B,
  tP_ValidityPeriodFormat := '11'B,
  tP_RejectDuplicates := '0'B,
  tP_MessageTypeIndicator := tsc_MT_SMS_SUBMIT,
  tP_MessageReference := ?,
  tP_DestinationAddress := cr_TP_AddressAny,
  tP_ProtocolIdentifier := cr_TP_ProtocolIdentifier,
  tP_DataCodingScheme_Type := ?,
  tP_ValidityPeriod  := ?,
  tP_UserDataLength := int2oct(160,1),
  tP_UserData := ? // any data will do: 140 octets
};

template (value) SMS_SUBMIT_REPORT_Type cs_SMS_SUBMIT_REPORT :=
{
  spare1 := '0'B,
  tP_UserDataHeaderIndicator := '0'B,
  spare4 := '0000'B,
  tP_MessageTypeIndicator := tsc_MT_SMS_SUBMIT_REPORT,
  tP_FailureCause := omit,
  tP_ParameterIndicator := cs_TP_ParameterIndicator,
  tP_ServiceCentreTimeStamp := f_GetSC_TimeStamp(),
  tP_ProtocolIdentifier := cs_TP_ProtocolIdentifier,
  tP_DataCodingScheme_Type := omit,
  tP_UserDataLength := omit,
  tP_UserData := omit
};

/* End SM-TP PDU Constraints */
} // group SMS_Templates_Group

group NAS_Specific_Templates {

template NAS_MessageContainer cr_NAS_MsgContainer_SMS (template (present) octetstring p_SMS_Message) :=
{
  iei         := omit,
  iel         := ?,
  smsmessage  := p_SMS_Message
};

template (value) NAS_MessageContainer cs_NAS_MsgContainer_SMS (template (value) octetstring p_SMS_Message) :=
{
  iei         := omit,
  iel         := int2oct(lengthof (p_SMS_Message), 1),
  smsmessage  := p_SMS_Message
};

template NAS_UL_Message_Type cr_SMS_UL_NAS_Transport (SecurityHeaderType p_SecurityHeader,
                                                      template NAS_MessageContainer p_NasMessage) :=
{
  ul_NAS_TRANSPORT := {
    securityHeaderType             := p_SecurityHeader,
    protocolDiscriminator          := tsc_PD_EMM,
    messageType                    := tsc_MT_UL_NASTransport,
    nasMessage                     := p_NasMessage
  }
};

template (value) NAS_DL_Message_Type cs_SMS_DL_NAS_Transport (SecurityHeaderType p_SecurityHeader,
                                                              template (value) NAS_MessageContainer p_NasMessage) :=
{
  dl_NAS_TRANSPORT := {
    securityHeaderType             := p_SecurityHeader,
    protocolDiscriminator          := tsc_PD_EMM,
    messageType                    := tsc_MT_DL_NASTransport,
    nasMessage                     := p_NasMessage
  }
};

} // group NAS_Specific_Templates

group LocalFunctions {

function f_IA5_2oct(charstring p_ASCII_String)
return octetstring
{
    var integer i;
    var integer k;
    var integer v_Length := lengthof(p_ASCII_String);
    var integer v_Temp;
    var octetstring v_Noctets :=''O;
    var bitstring   v_TempBitSrc := ''B;
    var bitstring   v_TempBitDes := ''B;

    if ((v_Length<=0) or (v_Length>160) or (((v_Length *7) mod 8) != 0))
    {
       FatalError(__FILE__, __LINE__, "Invalid value of input string length.");
    }

    for(i:=0; i<v_Length; i:=i+1)
    {
      v_Temp := char2int(p_ASCII_String[i]);
      v_TempBitSrc := int2bit(v_Temp, 8);
      
      for(k:=1; k<=7; k:=k+1)
        {
          
          v_TempBitDes := v_TempBitSrc[8-k] & v_TempBitDes;
          
          if(((7*i+k) mod 8) == 0)
            {
              
              v_Noctets := v_Noctets & bit2oct(v_TempBitDes);
              v_TempBitDes := ''B;
            }
        }
    }
    
    return v_Noctets;
    
} // f_IA5_2oct

/******************************************************************************/
/* calculation of the TP Service Centre Time Stamp acc. to TS 23.040 cl. 9.2.3.11 */

function fl_SwappedNibbles(integer p_Val) return H2_Type
{
  var integer v_LowNibble  := p_Val mod 10;
  var integer v_HighNibble := (p_Val / 10) mod 10;
  
  return int2hex(v_LowNibble, 1) & int2hex(v_HighNibble, 1);
}

function f_GetSC_TimeStamp() return TP_ServiceCentreTimeStamp_Type
{ /* returns the ServiceCentreTimeStamp with current time */
  // Example:
  // 2002 April 18, 15:32:46, timezone=4
  // f_GetSC_TimeStamp returns 20408151236440
  var Struct_tm_Type v_LocalTime;
  var integer v_TimezoneSeconds;
  var integer v_TimezoneVal;
  var integer v_SignVal := 0;  // positive value per default
  var H2_Type v_Year;
  var H2_Type v_Month;
  var H2_Type v_Day;
  var H2_Type v_Hour;
  var H2_Type v_Minute;
  var H2_Type v_Second;
  var H2_Type v_Timezone;
  
  fx_GetSystemTime(v_LocalTime, v_TimezoneSeconds);
  
  v_Year      := fl_SwappedNibbles(v_LocalTime.tm_year + 1900);     /* acc. to definition of struct tm */
  v_Month     := fl_SwappedNibbles(v_LocalTime.tm_mon + 1);         /* acc. to definition of struct tm */
  v_Day       := fl_SwappedNibbles(v_LocalTime.tm_mday);
  v_Hour      := fl_SwappedNibbles(v_LocalTime.tm_hour);
  v_Minute    := fl_SwappedNibbles(v_LocalTime.tm_min mod 60);      /* v_LocalTime.tm_min can be 0..61 on some systems */
  v_Second    := fl_SwappedNibbles(v_LocalTime.tm_sec);
  
  /* Calculation of the timezone (-> 23.040): */
  if (v_LocalTime.tm_isdst > 0) {                 /* The value contained in the Time Zone field must take into account daylight saving time, such that when the sending entity changes from regular
                                                     (winter) time to daylight saving (summer) time, there is a change to the value in the Time Zone field,
                                                     for example in the UK the winter setting is 00000000 and the summer setting is 01000000. */
    v_TimezoneSeconds := v_TimezoneSeconds + 3600;
  }
  
  if (v_TimezoneSeconds < 0) {
    v_TimezoneSeconds := -v_TimezoneSeconds;
    v_SignVal := 128;                             /* In the first of the two semi octets, the first bit (bit 3 of the seventh octet of the TP Service Centre Time Stamp field)
                                                     represents the algebraic sign of this difference (0: positive, 1: negative) */
  }
  v_TimezoneVal := v_TimezoneSeconds / (60 * 15); /* The Time Zone indicates the difference, expressed in quarters of an hour, between the local time and GMT. */
  v_TimezoneVal := v_TimezoneVal mod 128;         /* ... just to be sure */
  v_TimezoneVal := v_TimezoneVal + v_SignVal;     /* set the upper bit */
  
  v_Timezone  := fl_SwappedNibbles(v_TimezoneVal);
  
  return v_Year & v_Month & v_Day & v_Hour & v_Minute & v_Second & v_Timezone;
}

} // group LocalFunctions

} // module
