Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

Implementing Custom Timezone

krstech
2022-03-08
2022-03-09
  • krstech

    krstech - 2022-03-08

    Codesys V3.5 SP17 Patch 3 (64bit)
    Pi package: 4.2.0.0
    PFC200 package: 4.2.0.0

    Here's my scripts for implementing local timezone for Eastern Standard Time - Toronto Canada.
    Using UTIL Functions - getDateTime() and localDateTime()

    1. Installed UTIL Library 3.5.17.0
    2. Add declaration to Global Variable List
    3. Created POU: prgTimeZone
    4. Created Datatype: TimezoneInfo
    5. Created custom Function: tzoneDOW
    6. Created HMI screen
    7. Changed Timezone setting in Global Variable List to test and verify.

    1 Install UTIL Library

    Library Manager > Add Library > UTIL Library 3.5.17.0

    2 Global Variable List

    GLOBAL VARIABLE LIST
    code
    ~~~

    VAR_GLOBAL CONSTANT
    ( Eastern Timezone declaration for Toronto, Canada.
    DST begins on 2nd Sunday in March and EST begins on 1st Sunday in November by 1 hour.
    Note: Ontario has two timezones - Central & Eastern
    uiDay => 1..5 1=> first day of the month, 5 => last day of the month
    )

    // Coordinated Universal Time
    gc_tzTimeZoneUTC : TimeZone := (asgPeriod := [(sName:='UTC')]);
    
    // Eastern Timezone - Toronto
    gc_tzTimeZoneTOR : TimeZone :=
    (
        iBias := -300,      (* -300 minutes => -5 hours difference with respect to UTC with GMT -05:00              *)
        asgPeriod :=
        [(sName:='EST',     (* Eastern Standard Time - EST begins on 1st Sunday in November at 3:00am - Fallback    *)
          dtDate := (uiMonth := 11, eWeekday := WEEKDAY.SUNDAY, uiDay := 1, uiHour := 3, uiMinute := 0)
         ),
    
        ( sName :='DST',    (* Daylight Saving Time - DST begins on 2nd Sunday in March at 3:00am - Spring Forward *)
          dtDate := (uiMonth := 3,  eWeekday := WEEKDAY.SUNDAY, uiDay := 2, uiHour := 3, uiMinute := 0),
          iBias := 60       (* minutes - spring forward 1 hour in March *)
        )]
     );
    

    END_VAR

    3 POU: prgTimeZone

    PROGRAM prgTimeZone
    VAR

    utcDateTime     : ULINT;
    localDT         : ULINT;
    tZone           : ULINT;
    
    utcDate         : DATE;
    utcTime         : TIME_OF_DAY;
    utc_eWeekday    : UTIL.WEEKDAY;
    utc_sWeekday    : STRING(3);
    
    localDate       : DATE;
    localTime       : TIME_OF_DAY;
    local_eWeekday  : UTIL.WEEKDAY;
    local_sWeekday  : STRING(3);
    
    errorID         : UTIL.ERROR;
    period          : UTIL.PERIOD;
    status          : STRING(8);
    
    dst             : BOOL;
    localTimezoneInfo   : TimezoneInfo;
    

    END_VAR

    ( Set Eastern Timezone for Toronto, Canada - DST begins on 2nd Sunday in March and EST begins on 1st Sunday in November )

    ( Using FUNCTIONS: getTimeDate & localDateTime )

    // UTC
    utcDateTime := getDateTime();
    SeparateDateTime(uliDateTIme:=utcDateTime,eWeekday=>utc_eWeekday,datDate=>utcDate,todTime=>utcTime);
    utc_sWeekday := tzoneDOW(utc_eWeekday); // UTC Day of Week, 1= Mon, 2=TUE

    // EST/DST
    localDT := localDateTime(tzTimeZone:=gvl.gc_tzTimeZoneTOR,uliDateTIme:=utcDateTime,eErrorID=>errorID,ePeriod=>period);
    SeparateDateTime(uliDateTIme:=localDT,eWeekday=>local_eWeekday,datDate=>localDate,todTIme=>localTime);

    tZone := (utcDateTime - localDT) / (1000 * 3600); // utc-local time difference in hours
    local_sWeekday := tzoneDOW(local_eWeekday); // Local Time Day of Week, 1= Mon, 2=TUE

    ( LOCAL TIMEZONE INFO - for HMI display purposes only )

    localTimezoneInfo.est_iBias := gvl.gc_tzTimeZoneTOR.iBias;
    localTimezoneInfo.est_sName := gvl.gc_tzTimeZoneTOR.asgPeriod[1].sName;
    localTimezoneInfo.est_month := gvl.gc_tzTimeZoneTOR.asgPeriod[1].dtDate.uiMonth;
    localTimezoneInfo.est_eWeekday := gvl.gc_tzTimeZoneTOR.asgPeriod[1].dtDate.eWeekday;
    localTimezoneInfo.est_sWeekday := tzoneDOW(gvl.gc_tzTimeZoneTOR.asgPeriod[1].dtDate.eWeekday); // Function(tzoneDOW)
    localTimezoneInfo.est_day := gvl.gc_tzTimeZoneTOR.asgPeriod[1].dtDate.uiDay;
    localTimezoneInfo.est_hour := gvl.gc_tzTimeZoneTOR.asgPeriod[1].dtDate.uiHour;
    localTimezoneInfo.est_minute := gvl.gc_tzTimeZoneTOR.asgPeriod[1].dtDate.uiMinute;

    localTimezoneInfo.dst_iBias := gvl.gc_tzTimeZoneTOR.asgPeriod[2].iBias;
    localTimezoneInfo.dst_sName := gvl.gc_tzTimeZoneTOR.asgPeriod[2].sName;
    localTimezoneInfo.dst_month := gvl.gc_tzTimeZoneTOR.asgPeriod[2].dtDate.uiMonth;
    localTimezoneInfo.dst_eWeekday := gvl.gc_tzTimeZoneTOR.asgPeriod[2].dtDate.eWeekday;
    localTimezoneInfo.dst_sWeekday := tzoneDOW(gvl.gc_tzTimeZoneTOR.asgPeriod[2].dtDate.eWeekday); // Function(tzoneDOW)
    localTimezoneInfo.dst_day := gvl.gc_tzTimeZoneTOR.asgPeriod[2].dtDate.uiDay;
    localTimezoneInfo.dst_hour := gvl.gc_tzTimeZoneTOR.asgPeriod[2].dtDate.uiHour;
    localTimezoneInfo.dst_minute := gvl.gc_tzTimeZoneTOR.asgPeriod[2].dtDate.uiMinute;

    IF period = 1 THEN status := 'STANDARD'; dst := FALSE;
    ELSIF period = 2 THEN status := 'DAYLIGHT'; dst := TRUE;
    ELSE status := 'UNKNOWN'; dst := FALSE;
    END_IF

    4 Datatype: TimeZoneInfo(STRUCT)

    TYPE TimezoneInfo :
    STRUCT

    est_iBias           : INT;
    est_sName           : STRING(3);
    est_month           : UINT; 
    est_eWeekday        : UTIL.WEEKDAY;         
    est_sWeekday        : STRING(3);
    est_day             : UINT;                 
    est_hour            : UINT;
    est_minute          : UINT;
    
    dst_sName           : STRING(3);
    dst_month           : UINT;
    dst_eWeekday        : UTIL.WEEKDAY;         // 1=monday 
    dst_sWeekday        : STRING(3);
    dst_day             : UINT;                 1..5 1=> first day in this month 5 => last day in this month
    dst_hour            : UINT;
    dst_minute          : UINT;
    dst_iBias           : INT;
    

    END_STRUCT
    END_TYPE

    5 Function: tzoneDOW

    FUNCTION tzoneDOW : string
    VAR_INPUT
    eWeekday : UTIL.WEEKDAY;
    END_VAR
    VAR
    END_VAR

    ( Local Timezone Day of Week )

    CASE eWeekday OF

    1 : tzoneDOW := 'MON';
    2 : tzoneDOW := 'TUE';
    3 : tzoneDOW := 'WED';
    4 : tzoneDOW := 'THU';
    5 : tzoneDOW := 'FRI';
    6 : tzoneDOW := 'SAT';
    7 : tzoneDOW := 'SUN';

    END_CASE

    6 HMI

    see attachment

    -krstech integration

     

    Related

    Talk.ru: 1
    Talk.ru: 2


    Last edit: krstech 2022-03-09
  • krstech

    krstech - 2022-03-08

    Attached snapshots for your reference.
    -krstech

     

    Last edit: krstech 2022-03-08
  • hermsen

    hermsen - 2022-03-08

    What exactly is your question β‰οΈπŸ˜‰πŸ’ͺ

     
    • krstech

      krstech - 2022-03-08

      Do not have a question.
      It is a working example

      krstech

      On Mar 8, 2022, at 6:36 PM, h-hermsen no-reply@codesys.com wrote:

      ο»Ώ
      What exactly is your question β‰οΈπŸ˜‰πŸ’ͺ

      Implementing Custom Timezone

      Sent from forge.codesys.com because you indicated interest in https://forge.codesys.com/forge/talk/Engineering/

      To unsubscribe from further messages, please visit https://forge.codesys.com/auth/subscriptions/

       

      Last edit: krstech 2022-03-08
      • hermsen

        hermsen - 2022-03-09

        Hi, Any all contributions of code to Forge is fantastic but I feel that your cide nippets like this are best to be post here:
        https://forge.codesys.com/tol/iec-snippets/snippets/

        That way your code snippet is neatly organized and availabe on a central definded location. We (the community) hope to see more of your contributions there.

        PS. you can also use your HOME/Blog location for this or open a project in the projects section.

        have 😊 fun!

         
  • hermsen

    hermsen - 2022-03-08
     

    Last edit: hermsen 2022-03-08

Log in to post a comment.