Добавьте много секунд к TDateTime в C Builder 2009

#c #time #tdatetime #c builder-2009

#c #время #tdatetime #c builder-2009

Вопрос:

Я использую C Builder 2009. У меня есть дата начала 2000/01/01 и количество секунд от этой временной метки. Я хочу создать a TDateTime с этой датой. Я создаю начальную точку TDateTime и добавляю секунды.

   TDateTime dt(2000,1,1,0,0,0,0);
  AnsiString sdt = "";
  DateTimeToString(sdt, "yyyy/mm/dd hh:nn:ss", dt);
  closeDateTime = dt;
  closeDateTime = IncSecond(closeDateTime,footer->secondsFromZeroDateOfFinishDocument);
  DateTimeToString(sdt, "yyyy/mm/dd hh:nn:ss", closeDateTime);
  

После добавления более 650 миллионов секунд время TDateTime увеличивается всего на 23 дня, но должно увеличиться более чем на 20 лет. Смотрите скриншоты ниже.

Как я могу добавить это количество секунд к a TDateTime ?

изображение

изображение

изображение

Комментарии:

1. Я не вижу проблемы с вашим кодом, и меня бы удивило, если IncSeconds бы это было сломано.

2. Я использую C Builder 2009.

3. Все ставки отменяются, если вы используете компилятор 11-летней давности .

4. Я не могу обновить компилятор.

5. @Botje на самом деле, в C Builder / Delphi 2009 и даже раньше DateUtils функции были не очень точными. Функции были переписаны в XE для решения проблем с точностью.

Ответ №1:

В вашем коде нет ничего плохого. И на самом деле, я не могу воспроизвести проблему, которую вы описываете, используя значения, которые вы показали. Результат, который я получаю 2020.09.30 08:32:21 , как и ожидалось.


При этом было известно, что функции в DateUtils модуле имели проблемы с точностью до XE, когда эти проблемы были исправлены. C Builder 2009 предшествует XE. Итак, если вы не можете перейти на последнюю версию, вы можете, по крайней мере, применить то же исправление, которое используется в более поздних версиях:

 #include <SysUtils.hpp>

namespace fixed {
    TDateTime __fastcall IncSecond(const TDateTime AValue, const __int64 ANumberOfSeconds = 1)
    {
        TTimeStamp TS = DateTimeToTimeStamp(AValue);
        double TempTime = TimeStampToMSecs(TS);
        // if the above call to TimeStampToMSecs() proves to be inaccurate (it did
        // in my test in C  , but worked fine in Delphi), you can use this instead:
        // double TempTime = (double(TS.Date) * double(MSecsPerDay))   double(TS.Time);
        TempTime = TempTime   (ANumberOfSeconds * MSecsPerSec);
        TS = MSecsToTimeStamp(TempTime);
        return TimeStampToDateTime(TS);
    }
}

TDateTime dt(2000,1,1,0,0,0,0);
AnsiString sdt = "";
DateTimeToString(sdt, "yyyy/mm/dd hh:nn:ss", dt);
closeDateTime = dt;
closeDateTime = fixed::IncSecond(closeDateTime,footer->secondsFromZeroDateOfFinishDocument);
DateTimeToString(sdt, "yyyy/mm/dd hh:nn:ss", closeDateTime);
  

Ответ №2:

Я нашел некоторые обходные пути. Я добавляю дни, а затем добавляю оставшиеся секунды. Я думаю, что это ошибка в RTL, но я не могу обновить эту кодовую базу.

   TDateTime dt(2000,1,1,0,0,0,0);
  AnsiString sdt = "";
  DateTimeToString(sdt, "yyyy/mm/dd hh:nn:ss", dt);
  closeDateTime = dt;
  int seconds = footer->secondsFromZeroDateOfFinis775hDocument;
  int days = seconds / 86400;
  int restOfSeconds = seconds - days*86400;
  closeDateTime = IncDay(closeDateTime,days);
  closeDateTime = IncSecond(closeDateTime,restOfSeconds);
  DateTimeToString(sdt, "yyyy/mm/dd hh:nn:ss", closeDateTime);
  

Комментарии:

1. К вашему сведению, int restOfSeconds = seconds - days*86400; можно упростить int restOfSeconds = seconds % 86400; и использовать Syutils::SecsPerDay константу вместо жесткого кодирования 86400 .