Раскладка UnixTime на составляющие

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Раскладка UnixTime на составляющие

Сообщение slyubez » 20.01.2018 08:53:14

Приветствую всех.

Прошу помочь с задачкой. Мне нужно сформировать функцию разложения числа UnixTime на составляющие (день, месяц, год, час, минута, секунда). В сети есть набор алгоритмов для такого разложения, однако когда я пытаюсь свериться со стандартными функциями модуля DateUtils, получается какая-то хрень. Вот мой код функции (оптимизировать я буду только после того, как все заработает):
Код: Выделить всё
function unixTimeToSLDateTime (ut: Int64): TSLDateTime;
var dt, dttmp: TSLDateTime;
    DaysBet, SecBetMod, secs: Int64;
    I, LeapYears, CurYrDays, dim, dimsum, tmp: Word;
begin
dt.year:=1970+(ut div SECONDSINYEAR);
secs:=0;
for I:=1970 to dt.year-1
  do if isLeapYear (I) then secs:=secs+SECONDSINLEAPYEAR
      else secs:=secs+SECONDSINYEAR;
CurYrDays := (ut - secs) div SECONDSINDAY;
dimsum:=0;
for I:=0 to 11
  do begin
      if I<>1
       then dim:=DAYSINMONTHARRAY [I]
       else if IsLeapYear (dt.year)
             then dim:=29 else dim:=28;
      dimsum:=dimsum+dim;
      if dimsum > CurYrDays
       then begin
             Dec (dimsum, dim);
             dt.month:=I+1;
             dt.day:=CurYrDays-dimsum+1;
             Break;
            end;
      secs:=secs+(dim*SECONDSINDAY);
     end;
secs:=ut-secs;
dt.hour:=secs div SECONDSINHOUR;
secs:=secs-(dt.hour*SECONDSINHOUR);
dt.minute:=secs div 60;
dt.second := secs mod 60;
Result:=dt;
end;


Вот фрагменты тестирующего кода:

Код: Выделить всё
type
TSLDateTime = record
               second, minute, hour, weekday,
                day, month: byte;
               year: word;
              end; 
...
function SLDateTimeToString (dt: TSLDateTime): String;
var s: String;
begin
s:=IntToStr (dt.day);
if dt.day<10 then s:='0'+s;
Result:=s+'.';
s:=IntToStr (dt.month);
if dt.month<10 then s:='0'+s;
Result:=Result+s+'.';
s:=IntToStr (dt.year);
Result:=Result+s+' ';
s:=IntToStr (dt.hour);
if dt.hour<10 then s:='0'+s;
Result:=Result+s+':';
s:=IntToStr (dt.minute);
if dt.minute<10 then s:='0'+s;
Result:=Result+s+':';
s:=IntToStr (dt.second);
if dt.second<10 then s:='0'+s;
Result:=Result+s;
end; 
...
var
  dt: TDateTime;
  U: Int64;
  s: String;
  sldt: TSLDateTime;
...
Memo1.Lines.Add ('UnixTimeToSLDateTime');
dt:=EncodeDate (2008, 2, 15)+EncodeTime (11, 31, 33, 0);
for I:=1 to 7
  do begin
      U:=DateTimeToUnix (dt);
      sldt:=unixTimeToSLDateTime (U);
      s:=IntToStr (U)+#9
       +DateToStr (dt)+' '+TimeToStr(dt)+#9+SLDateTimeToString (sldt);
      Memo1.Lines.Add (s);
      dt:=dt+10*1/4;
     end;


Добавлено спустя 2 минуты 26 секунд:
А вот вывод в мемо:
UnixTimeToSLDateTime
1203075093 15-2-08 11:31:33 15.02.2008 91:31:33
1203291093 17-2-08 23:31:33 17.02.2008 151:31:33
1203507093 20-2-08 11:31:33 20.02.2008 211:31:33
1203723093 22-2-08 23:31:33 22.02.2008 15:31:33
1203939093 25-2-08 11:31:33 25.02.2008 75:31:33
1204155093 27-2-08 23:31:33 27.02.2008 135:31:33
1204371093 1-3-08 11:31:33 01.03.2008 11:31:33


Чую, проблема простейшая, но не могу понять, где. Уже третий день мозг выносит. Заранее благодарен.
slyubez
постоялец
 
Сообщения: 174
Зарегистрирован: 31.03.2015 08:44:07

Re: Раскладка UnixTime на составляющие

Сообщение olegy123 » 20.01.2018 12:14:05

Конвертация времени (разложение на сек/мин/часы/дни/месяцы/года)
https://ru.wikipedia.org/wiki/UNIX-%D0% ... 0%BC%D1%8F

slyubez писал(а):однако когда я пытаюсь свериться со стандартными функциями модуля DateUtils

начало (нуль значение) у Unix времени равна 00:00:00 UTC 1 января 1970 года

начало (нуль значение) в Delphi/FPC времени равна 00:00:00 UTC 1 января 1900 года

Добавлено спустя 1 минуту 58 секунд:
slyubez писал(а):dt.year:=1970+(ut div SECONDSINYEAR);

еще присутствуют високосные года (когда февраль = 29дням)
простым делением не обойтись
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: Раскладка UnixTime на составляющие

Сообщение wofs » 20.01.2018 13:54:09

slyubez писал(а):однако когда я пытаюсь свериться со стандартными функциями модуля DateUtils


А чем вас не устраивают функции DateUtils ?
Код: Выделить всё
Function DateTimeToUnix(const AValue: TDateTime): Int64;
Function UnixToDateTime(const AValue: Int64): TDateTime;


Код: Выделить всё
DateTimeToStr(UnixToDateTime(0),DefaultFormatSettings,true);
//01.01.1970 0:00:00

DateTimeToStr(UnixToDate(1203075093),DefaultFormatSettings,true);
//15.02.2008 11:31:33


А дальше раскладывайте как хотите. Или вы хотите написать свою реализацию?

Добавлено спустя 34 минуты 58 секунд:
А если использовать
Код: Выделить всё
DateTimeToString

То можно форматировать вывод как душе угодно.
Аватара пользователя
wofs
постоялец
 
Сообщения: 379
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань

Re: Раскладка UnixTime на составляющие

Сообщение slyubez » 20.01.2018 14:37:57

Моя задача - разработать алгоритм раскодирования и перенести его на Ардуино. На нем все же не чистые Си или плюсы, так что я для разработки выбрал Паскаль, чтобы на нем же оттестировать результат через приведенные в Вашем посте функции.
Впрочем, в ссылке на Вики есть готовый алгоритм на С. Попробую тогда адаптировать его под Ардуино, а если не поможет, ещё раз займусь на Паскале.

Добавлено спустя 44 секунды:
Да, и спасибо за ссылку на Вики.
slyubez
постоялец
 
Сообщения: 174
Зарегистрирован: 31.03.2015 08:44:07

Re: Раскладка UnixTime на составляющие

Сообщение Cheb » 20.01.2018 16:09:53

Только не забывай ещё, что ардуино - 16-битный и int у него - [-32768..32767]
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: Раскладка UnixTime на составляющие

Сообщение slyubez » 20.01.2018 16:21:27

Только не забывай ещё, что ардуино - 16-битный

Помню. Использую uint32_t. Надо будет глянуть, есть ли у него поддержка uint64_t.
Наверное, тогда уж лучше сразу подготовить тест на С. Хотя на Паскале все это и нагляднее, и занимает меньше времени на написание.
slyubez
постоялец
 
Сообщения: 174
Зарегистрирован: 31.03.2015 08:44:07

Re: Раскладка UnixTime на составляющие

Сообщение mig-31 » 23.01.2018 13:16:04

А что вам мешает посмотреть на исходники UnixToDateTime и адаптировать под 16-бит.
mig-31
постоялец
 
Сообщения: 224
Зарегистрирован: 14.07.2011 13:46:48

Re: Раскладка UnixTime на составляющие

Сообщение slyubez » 27.01.2018 18:30:39

А что вам мешает посмотреть на исходники UnixToDateTime и адаптировать под 16-бит.

Непонимание отдельных вещей. В частности, функции Pred, используемой в этих исходниках.
slyubez
постоялец
 
Сообщения: 174
Зарегистрирован: 31.03.2015 08:44:07

Re: Раскладка UnixTime на составляющие

Сообщение Снег Север » 27.01.2018 23:14:40

slyubez писал(а):Непонимание отдельных вещей. В частности, функции Pred, используемой в этих исходниках.
Pred дает предыдущее значение любой переменной перечисляемого типа. Например, Pred('b') = 'a', Pred(1) = 0 и т.д.
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 3038
Зарегистрирован: 27.11.2007 16:14:47


Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 7

Рейтинг@Mail.ru