Есть ли в UniVerse 11.2.4+ собственный способ преобразования времени в UTC?

В примечаниях к выпуску UniVerse версии 11.2.4 упоминается конфигурация локального часового пояса, но она находится в контексте аудита. Это цитата:

Конфигурация местного часового пояса

До UniVerse 11.2.4 данные о дате и времени, хранящиеся в записях журнала аудита, основывались только на UTC. Начиная с UniVerse 11.2.4, UniVerse добавляет данные о дате и времени, основанные на местном часовом поясе, в записи журнала аудита. Данные хранятся в ячейке 19 для каждой записи. Название словаря для этого поля данных - TZINFO. Для получения дополнительной информации см. Функции безопасности UniVerse.

Поскольку UniVerse кажется способным работать с часовыми поясами изначально, означает ли это, что может быть способ легко сгенерировать метки даты / времени в формате UTC из моих значений EST/EDT?

Я отправляю данные в систему, которая хочет, чтобы даты были отформатированы в формате даты / времени ISO-8601 yyyy-MMddTHH:mm:ssZ, лайк 2015-06-02T15:55:22Z, с учетом часового пояса и летнего времени.

Я перерыл руководство по функциям безопасности и обнаружил следующее:

UniVerse также добавляет глобально каталогизированную программу, чтобы помочь пользователям получать информацию о дате и времени из журнала аудита (который вызывается двумя вышеупомянутыми полями I-дескриптора):

SUBROUTINE GETLOCALTIME
(
RESULT ;* OUT: output
TZOFF ;* IN: time zone offset
DATE ;* IN: UTC date
TIME ;* IN: UTC time
OP ;* IN: operation
;* 1: get local date
;* 2: get local time
;* 3: get local timezone id
;* 4: get local timezone daylight saving flag
)

(Поскольку я не использую возможности аудита UniVerse, я не думаю, что смогу с этим многое сделать, и при этом я не смог найти подпрограмму.)

Я также играл с популярным (?) DATE.UTILITY программа от PickWiki, но ее расчет даты начала / окончания перехода на летнее время кажется отключенным. Я сохраню эти вопросы для другого вопроса.

Это становится длинным, но я надеюсь, что кто-то может указать мне правильное направление, если есть новый параметр OCONV() или что-то, что я мог бы использовать.

На всякий случай это работает, я работаю на Windows Server 2008 R2.

Спасибо!

2 ответа

Время сложная вещь. Социально мы признали, что не только приемлемо изменять это 2 раза в год, мы уполномочили это! Все это хорошо для мясных машин, которые хотят понимать время, когда это удобно для нас, однако это заставляет нас раздражаться, когда наши репортажи "выглядят смешно".

Решение вашей проблемы не является исключительно простым, особенно если вы работаете с уже записанными датами. Даты и время во Вселенной обычно записываются на основе местного системного времени. Если это то, что вы пытаетесь сделать в будущем, вы должны отметить, какое смещение есть во время транзакции, или просто пометить элементы SYSTEM(99), что усложнило почти все остальные отчеты, которые вам понадобятся. В любом случае, это сложный вопрос, и он все еще может быть несколько несовершенным.

Вот кое-что, что могло бы помочь вам, если вы отвечаете за запись дат, в будущем.

SECONDS.SINCE.GMT.01.01.1970 = SYSTEM(99) 
CRT SECONDS.SINCE.GMT.01.01.1970:" Seconds since GMT Epoch Began"

NUMBER.OF.DAYS.SINCE.01.01.1970 = DATE() -732 
;* Day 0 in Pick is 12/31/1967 because Dick Pick so we subtract 732 from the pick date

SECONDS.SINCE.MIDNIGHT.LOCAL= TIME()
SECS.PER.DAY = 24 * 60 * 60
LOCAL.SECONDS.SINCE.GMT.01.01.1970 = NUMBER.OF.DAYS.SINCE.01.01.1970 * SECS.PER.DAY + FIELD(SECONDS.SINCE.MIDNIGHT.LOCAL,".",1) 
;*I drop the precision
CRT LOCAL.SECONDS.SINCE.GMT.01.01.1970: " Seconds since 01/01/1970 in local time"

OFFSET = (LOCAL.SECONDS.SINCE.GMT.01.01.1970 - SECONDS.SINCE.GMT.01.01.1970)
CRT "CURRENT.OFFSET IS ":INT((OFFSET / 60 )/ 60)
END

Который выводит следующее в моей системе, которая в настоящее время является PDT (хотя OCONV(DATE(),'DZ') сообщает об этом как PST.

1434472817 Seconds since GMT Epoch Began
1434447617 Seconds since 01/01/1970 in local time
CURRENT.OFFSET IS -7

Надеюсь, вы нашли это полезным.

Спасибо за подсказки. Вот моя реализация:

  SUBROUTINE FORMAT.ISO.8601 (IDATE, ITIME, RESULT, ERR.TEXT)

  * Don't step on the caller's variables.
  IN.DATE = IDATE
  IN.TIME = ITIME

  * Initialize the outbound variable.
  RESULT = ''

  IF NOT(NUM(IN.DATE)) THEN
     ERR.TEXT = 'Non-numeric internal date ' : DQUOTE(IN.DATE) : ' when numeric required.'
     RETURN
  END

  IF NOT(NUM(IN.DATE)) THEN
     ERR.TEXT = 'Non-numeric internal time ' : DQUOTE(IN.TIME) : ' when numeric required.'
     RETURN
  END

  * SYSTEM(99) is based on 1/1/1970.
  SECONDS.SINCE.GMT.01.01.1970 = SYSTEM(99)

  * Day 0 in Pick is 12/31/1967
  * Subtract 732 to equalize the starting dates.
  NUMBER.OF.DAYS.SINCE.01.01.1970 = DATE() - 732

  SECONDS.SINCE.MIDNIGHT.LOCAL= TIME()
  SECS.PER.DAY = 24 * 60 * 60
  LOCAL.SECONDS.SINCE.GMT.01.01.1970 = NUMBER.OF.DAYS.SINCE.01.01.1970 * SECS.PER.DAY + FIELD(SECONDS.SINCE.MIDNIGHT.LOCAL,".",1)

  OFFSET = LOCAL.SECONDS.SINCE.GMT.01.01.1970 - SECONDS.SINCE.GMT.01.01.1970

  OFFSET = INT((OFFSET / 60 )/ 60)

  OTIME = OCONV(IN.TIME, 'MTS')
  IF OTIME = '' THEN
     ERR.TEXT = 'Bad internal time ' : DQUOTE(IN.TIME) : '.'
     RETURN
  END

  HOURS = FIELD(OTIME, ':', 1)
  MINUTES = FIELD(OTIME, ':', 2)
  SECONDS = FIELD(OTIME, ':', 3)

  HOURS -= OFFSET
  IF HOURS >= 24 THEN
     IN.DATE += 1
     HOURS = HOURS - 24
  END
  HOURS = HOURS 'R%2'

  ODATE = OCONV(IN.DATE, 'D4/')
  IF ODATE = '' THEN
     ERR.TEXT = 'Bad internal date ' : DQUOTE(IN.DATE) : '.'
     RETURN
  END

  DMONTH = FIELD(ODATE, '/', 1)
  DDAY = FIELD(ODATE, '/',2)
  DYEAR = FIELD(ODATE, '/',3)

  RESULT = DYEAR : '-' : DMONTH : '-' : DDAY : 'T' : HOURS : ':' : MINUTES : ':' : SECONDS : 'Z'

  RETURN

END

Вот мой тестовый комплект:

  CRT 'Testing right now.'
  IDATE = DATE()
  ITIME = TIME()
  CALL FORMAT.ISO.8601 (IDATE, ITIME, RESULT, ERR.TEXT)
  IF ERR.TEXT THEN
     CRT 'ERR.TEXT: ' : ERR.TEXT
  END ELSE
     CRT 'RESULT: ' : RESULT
  END

  CRT
  CRT 'Testing an hour ago.'
  IDATE = DATE()
  ITIME = TIME()
  ITIME = ITIME - (60*60)
  IF ITIME < 0 THEN
     ITIME += (24*60*60)
     IDATE -= 1
  END
  CALL FORMAT.ISO.8601 (IDATE, ITIME, RESULT, ERR.TEXT)
  IF ERR.TEXT THEN
     CRT 'ERR.TEXT: ' : ERR.TEXT
  END ELSE
     CRT 'RESULT: ' : RESULT
  END

  CRT
  CRT 'Testing an hour from now.'
  IDATE = DATE()
  ITIME = TIME()
  ITIME = ITIME + (60*60)
  IF ITIME > (24*60*60) THEN
     ITIME -= (24*60*60)
     IDATE += 1
  END
  CALL FORMAT.ISO.8601 (IDATE, ITIME, RESULT, ERR.TEXT)
  IF ERR.TEXT THEN
     CRT 'ERR.TEXT: ' : ERR.TEXT
  END ELSE
     CRT 'RESULT: ' : RESULT
  END

END

Вот мой тестовый прогон:

  >T$FORMAT.ISO.8601
  Testing right now.
  RESULT: 2017-03-29T00:47:22Z

  Testing an hour ago.
  RESULT: 2017-03-28T23:47:22Z

  Testing an hour from now.
  RESULT: 2017-03-29T01:47:22Z
Другие вопросы по тегам