My client has seven iSeries systems and the time is set by hand on each.
This causes a swing of several minutes from the slowest to the fastest.

A number of good tools exist that use SMTP to get the correct time from
the internet or perhaps even the more accurate GPS system for iSeries.
Most are written in 'C' and/or use sockets programming. These methods
and SMTP all want to use the standard TCP port of 123 for time services.

My problem was that the clients network management group has this port
blocked at the firewall. So with some investigation I found that FTPing
into the U.S. Navy time server I would get a welcome message containing
the UTC time. Now this method has more overhead than standard SMTP and
the accuracy will suffer. On my oldest and slowest system I'm finding
the time to be 8 - 10 seconds slow. This is still far better than manual
setting the clock. 


The setup is quite simple.

First create a dummy file for the compile requirement.

CRTPF FILE(QTEMP/FTPLOG) RCDLEN(132)

You will also need to create a source physical file named FTPTIME.
Add to this file (using SEU) a TXT member named FTP.
Edit the member adding these two lines: 

anonymous your@email.com 
quit 

Now compile this CLP interactively with enough authority to change the
sysval QTIME. Note: The line "DCL VAR (&UPDATE) TYPE(*LGL) VALUE('0')"
must be changed to ('1') for the system value to be changed. 

If you wish to automate the Daylight saving time adjustment of your sysval
QUTCOFFSET use the 2nd small CLP. Note: the values are for the East coast
U.S. only. This program can be setup in any basic job scheduler to run
every Sunday at 2:00. 

Code: 


 /********************************************************************+
|                                                                    +
|  Program FTPTIME set the system time using FTP                     +
|                                                                    +
|  FTP to the US Navy time site and capture the login text           +
|  which contains the current UTC time.  Then set the system time.   +
|                                                                    +
|  Note: Job must run with authority that can CHGSYSVAL QTIME        +
|        This program requires you correctly set the SYSVAL          +
|        QUTCOFFSET for your time zone.                              +
|  Tip: Using your browser go to www.time.gov for your time zone     +
|        offset value.                                               +
|                                                                    +
|  Doug Hart  1/31/2022                                              +
|                                                                    +
+*********************************************************************/

             PGM

/*********************************************************************/
/* Local Variables                                                   */
/*********************************************************************/

                    /* Switch 0=no update, 1=update */
             DCL        VAR(&UPDATE) TYPE(*LGL) VALUE('0')

             DCL        VAR(&TGTSYS) TYPE(*CHAR) LEN(30) +
                          VALUE('TYCHO.USNO.NAVY.MIL')
             DCL        VAR(&CMPSTR) TYPE(*CHAR) LEN(8) +
                          VALUE('230-USNO') /* line compare string */
             DCL        VAR(&UTCSYSVAL) TYPE(*CHAR) LEN(5)
             DCL        VAR(&UTC) TYPE(*DEC) LEN(2 0)
             DCL        VAR(&UTCSIGN) TYPE(*CHAR) LEN(1)
             DCL        VAR(&HH) TYPE(*CHAR) LEN(2)
             DCL        VAR(&MM) TYPE(*CHAR) LEN(2)
             DCL        VAR(&SS) TYPE(*CHAR) LEN(2)
             DCL        VAR(&HHN) TYPE(*DEC) LEN(2 0)
             DCL        VAR(&TIME) TYPE(*CHAR) LEN(6)
             DCL        VAR(&QTIME) TYPE(*CHAR) LEN(6)
/********************************************************************/
/*     Setup variables for QCLSCAN program                          */
/********************************************************************/
             DCL        VAR(&STRING) TYPE(*CHAR) LEN(132)
             DCL        VAR(&STRLEN) TYPE(*DEC) LEN(3 0) VALUE(132)
             DCL        VAR(&STRPOS) TYPE(*DEC) LEN(3 0) VALUE(25)
             DCL        VAR(&PATTERN) TYPE(*CHAR) LEN(1) +
                          VALUE(':')
             DCL        VAR(&PATLEN) TYPE(*DEC) LEN(3 0) VALUE(1)
             DCL        VAR(&TRANSLATE) TYPE(*CHAR) LEN(1) VALUE('0')
             DCL        VAR(&TRIM) TYPE(*CHAR) LEN(1) VALUE('0')
             DCL        VAR(&WILD) TYPE(*CHAR) LEN(1) VALUE(' ')
             DCL        VAR(&RESULT) TYPE(*DEC) LEN(3 0) VALUE(1)
/********************************************************************/
/*     File in QTEMP that will be parsed for time string            */
/*     To compile program, file must be created and in libl         */
/********************************************************************/
             DCLF       FILE(FTPLOG)
/********************************************************************/
/* Get UTC time offset hours and + or - sign from sysval            */
/********************************************************************/
             RTVSYSVAL  SYSVAL(QUTCOFFSET) RTNVAR(&UTCSYSVAL)
             CHGVAR     VAR(&UTCSIGN) VALUE(%SST(&UTCSYSVAL 1 1))
             CHGVAR     VAR(&UTC) VALUE(%SST(&UTCSYSVAL 2 2))
/********************************************************************/
/* Build the FTP login file.                                        */
/*   This file has only two record holding the password and email   */
/*   and the FTP command QUIT needed for the Navy FTP server.       */
/*   ex:  ANONYMOUS                             */
/*        QUIT                                                      */
/*   Note: This can be setup once manually using SEU                */
/********************************************************************/
        /*   CRTSRCPF   FILE(*LIBL/FTPTIME) RCDLEN(92) MBR(FTP) */
/********************************************************************/
/* Delete/Create the FTP transfer log file                          */
/********************************************************************/
             DLTF       FILE(QTEMP/FTPLOG)
             MONMSG     MSGID(CPF0000)
             CRTPF      FILE(QTEMP/FTPLOG) RCDLEN(132) MBR(FTPLOG)
/********************************************************************/
/* Execute FTP transfer                                             */
/********************************************************************/
             OVRDBF     FILE(INPUT) TOFILE(*LIBL/FTPTIME) MBR(FTP)
             OVRDBF     FILE(OUTPUT) TOFILE(QTEMP/FTPLOG) MBR(FTPLOG)
             STRTCPFTP  RMTSYS(&TGTSYS)
             DLTOVR     FILE(*ALL)
/********************************************************************/
/* Parse FTPLOG file for time string                                */
/********************************************************************/
 READ:       RCVF
             MONMSG     MSGID(CPF0864) EXEC(GOTO CMDLBL(END))
             /* End of file found and record not found = error */

             IF         COND(%SST(&FTPLOG 1 8) = &CMPSTR) THEN(DO) +
/********************************************************************/
/* Found time string line in log starting with '230-USNO'           */
/* Now parse the line for ':' to get time position                  */
/* Then convert the string to HH MM SS values                       */
/********************************************************************/

             CHGVAR     VAR(&STRING) VALUE(&FTPLOG)
             CALL       PGM(QCLSCAN) PARM(&STRING &STRLEN &STRPOS +
                          &PATTERN &PATLEN &TRANSLATE &TRIM &WILD +
                          &RESULT)
             IF         COND(&RESULT = 0) THEN(GOTO CMDLBL(END))
             /* Time ':' not found in string = error */

             CHGVAR     VAR(&RESULT) VALUE(&RESULT - 2)
             CHGVAR     VAR(&HH) VALUE(%SST(&FTPLOG &RESULT 2))
             CHGVAR     VAR(&RESULT) VALUE(&RESULT + 3)
             CHGVAR     VAR(&MM) VALUE(%SST(&FTPLOG &RESULT 2))
             CHGVAR     VAR(&RESULT) VALUE(&RESULT + 3)
             CHGVAR     VAR(&SS) VALUE(%SST(&FTPLOG &RESULT 2))

             CHGVAR     VAR(&HHN) VALUE(&HH)
             IF         COND(&UTCSIGN = '-') THEN(DO)
             CHGVAR     VAR(&HHN) VALUE(&HHN - &UTC)
             IF         COND(&HHN < 0) THEN(CHGVAR VAR(&HHN) +
                          VALUE(24 + &HHN))
             ENDDO
             ELSE       CMD(DO) /* &UTCSIGN = '+' */
             CHGVAR     VAR(&HHN) VALUE(&HHN + &UTC)
             IF         COND(&HHN > 23) THEN(CHGVAR VAR(&HHN) +
                          VALUE(&HHN - 24))
             ENDDO
             CHGVAR     VAR(&HH) VALUE(&HHN)
/********************************************************************/
/* Set the system value QTIME                                       */
/********************************************************************/
             CHGVAR     VAR(&TIME) VALUE(&HH || &MM || &SS)
             RTVSYSVAL  SYSVAL(QTIME) RTNVAR(&QTIME)
             IF         COND(&UPDATE) +
               THEN(CHGSYSVAL  SYSVAL(QTIME) VALUE(&TIME))
             SNDPGMMSG  MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('System +
                          time changed from' |> %SST(&QTIME 1 2) || +
                          ':' || %SST(&QTIME 3 2) || ':' || +
                          %SST(&QTIME 5 2) |> 'to' |> &HH || ':' || +
                          &MM || ':' || &SS |> 'by FTPTIME +
                          program') MSGTYPE(*INFO)

             RETURN     /* Good completion */
             ENDDO

             GOTO       CMDLBL(READ) /* get next record loop */

/********************************************************************/
/* On error send mesage                                             */
/********************************************************************/
 END:        SNDPGMMSG  MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('FTP +
                          time process ended in ERROR.  Check +
                          joblog for details, or review the QTEMP +
                          files FTPCMD and FTPLOG.') MSGTYPE(*ESCAPE)

             ENDPGM


/* ----------------------------------------------------------------- +
 |  Program: ADJUTC Adjust UTC Sysval                                +
 |  Date   : 2/05/2022                                               +
 |  Author : D. Hart                                                 +
 |                                                                   +
 |  Function: Adjust for Daylight Saving Time the system value       +
 |            QUTCOFFSET.  This is only for the Eastern US time zone +
 |            Run this job every Sunday at 02:00 in system job       +
 |            scheduler.                                             +
 |                                                                   +
 |  Coordinated Universal Time -4 hours; Daylight Saving Time        +
 |  Coordinated Universal Time -5 hours; Not Daylight Saving Time    +
 |                                                                   +
 L ----------------------------------------------------------------- */

             PGM

             DCL        VAR(&MONTH) TYPE(*CHAR) LEN(2)
             DCL        VAR(&DAY) TYPE(*CHAR) LEN(2)


             RTVSYSVAL  SYSVAL(QMONTH) RTNVAR(&MONTH)
             RTVSYSVAL  SYSVAL(QDAY) RTNVAR(&DAY)

             /* 1ST Sunday in April start Daylight Saving Time */
             IF         COND(&MONTH = '04' *AND &DAY *LE '07') THEN( +
                CHGSYSVAL SYSVAL(QUTCOFFSET) VALUE('-0400'))

             /* Last Sunday in October end Daylight Saving Time */
             IF         COND(&MONTH = '10' *AND &DAY *GE '25') THEN( +
                CHGSYSVAL SYSVAL(QUTCOFFSET) VALUE('-0500'))

             ENDPGM