Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [BCB2009] TDateTime - Результат сравнения, Интервал между датами 
:(
    Опции темы
MuForum
Дата 13.9.2009, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 427
Регистрация: 13.6.2007
Где: Молдова, Кишинев

Репутация: 1
Всего: 4



Доброе время суток.
Работаю на "Borland C++ Builder 2009".

# Задача: Сравнить два объекта TDateTime и вернуть результат разницы дней, часов, минут и секунд в строке.
- Возвращаемый результат: XX days HH:mm:ss; (01 days 12:03:15)
- Я решил эту задачу, однако реализация мне не очень нравится.

Код

#include <DateUtils.hpp> // DaysBetween;
...
AnsiString GetDifDateTime(TDateTime dtSource, TDateTime dtDest)
{
    AnsiString sResult = "";
    // ----
    int iDays = 0;
    __int64 iRes = 0, iDif = 0;
    // ----
    iDays = DaysBetween(dtSource, dtDest);
    if(iDays < 10) sResult += "0";
    sResult += (String)iDays + " days ";
    iDif = iDays * 24;
    // ----
    iRes = HoursBetween(dtSource, dtDest);
    if(iRes > 24) iRes = iRes - iDif;
    if(iRes < 10) sResult += "0";
    sResult += (String)iRes + ":";
    iDif *= 60;
    if(iRes > 0) iDif += (iRes * 60);
    // ----
    iRes = MinutesBetween(dtSource, dtDest);
    if(iRes > 24) iRes = iRes - iDif;
    if(iRes < 10) sResult += "0";
    sResult += (String)iRes + ":";
    iDif *= 60;
    if(iRes > 0) iDif += (iRes * 60);
    // ----
    iRes = SecondsBetween(dtSource, dtDest);
    if(iRes > 24) iRes = iRes - iDif;
    if(iRes < 10) sResult += "0";
    sResult += (String)iRes;
    // ----
    return sResult;
}



P.S. -> Если кто-то может предложить лучший способ вычисления, буду рад.

Это сообщение отредактировал(а) MuForum - 13.9.2009, 17:04


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа!" (Р. Шекли)
PM MAIL WWW ICQ Skype MSN   Вверх
Efs
Дата 13.9.2009, 18:24 (ссылка)  | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 31.8.2009

Репутация: нет
Всего: нет



Хм.. а почему бы не оперировать с типами TDateTime, встроенными в BCPP, а не со строками ? 

PM MAIL   Вверх
smoke_man
Дата 13.9.2009, 18:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 447
Регистрация: 25.1.2007
Где: Рязань

Репутация: 9
Всего: 17



Например, так:
Код

    unsigned short hour,min,sec,msec;
    unsigned short d,m,y;    
    TDateTime t1 = Now();
    Sleep(2000);
    TDateTime t2 = Now();
    TDateTime t3 = t2-t1;
    t3.DecodeTime(&hour,&min,&sec,&msec);
    t3.DecodeDate(&y,&m,&d);



--------------------
0x2b|~0x2b
PM MAIL ICQ GTalk   Вверх
MuForum
Дата 13.9.2009, 22:44 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 427
Регистрация: 13.6.2007
Где: Молдова, Кишинев

Репутация: 1
Всего: 4



Цитата(smoke_man @ 13.9.2009,  18:41)
Например, так:
Код

    unsigned short hour,min,sec,msec;
    unsigned short d,m,y;    
    TDateTime t1 = Now();
    Sleep(2000);
    TDateTime t2 = Now();
    TDateTime t3 = t2-t1;
    t3.DecodeTime(&hour,&min,&sec,&msec);
    t3.DecodeDate(&y,&m,&d);

Данный способ хорош, НО, он не правильно определяет дату. (год, месяц, день)


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа!" (Р. Шекли)
PM MAIL WWW ICQ Skype MSN   Вверх
Efs
Дата 14.9.2009, 06:28 (ссылка)   | (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 31.8.2009

Репутация: нет
Всего: нет



Есть одна хорошая штука в билдере - DateTimePicker. С него можно брать заданную дату и время:
Код

TDateTime td1;
td1=(TDateTime)(DateTimePicker1->DateTime.DateString());

Получив дату и время таким образом, можно выполнять сравнение. Другое дело, если вы будете брать данные из файлов. 

PM MAIL   Вверх
MuForum
Дата 14.9.2009, 07:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 427
Регистрация: 13.6.2007
Где: Молдова, Кишинев

Репутация: 1
Всего: 4



Цитата(Efs @ 14.9.2009,  06:28)
Есть одна хорошая штука в билдере - DateTimePicker. С него можно брать заданную дату и время:
Код

TDateTime td1;
td1=(TDateTime)(DateTimePicker1->DateTime.DateString());

Получив дату и время таким образом, можно выполнять сравнение. Другое дело, если вы будете брать данные из файлов.

Вы не поняли задачу.
С получением даты и времени проблем не возникает.
Проблема возникает с вычитанием двух TDateTime -> Результат времени корректен, а вот результат даты нет.
Код

    unsigned short hour,min,sec,msec;
    unsigned short d,m,y;    
    TDateTime t1 = Now();
    Sleep(2000);
    TDateTime t2 = Now();
    TDateTime t3 = t2-t1;
    t3.DecodeTime(&hour,&min,&sec,&msec);
    t3.DecodeDate(&y,&m,&d);
....
Результаты:
hour = 0;
min = 0;
sec = 0;
msec = 0;
y = 1899;
m = 12;
d = 30;

- Я тоже так сделал в первый раз, но из-за не корректного результата даты отказался.
- Может я что-то не так делаю, подскажите.


P.S. -> Ещё раз уточняю задание. Есть два объекта TDateTime, мне необходимо получить их разность.

Добавлено @ 08:03
Кстати, пробовал и в ручную получить разницу даты и записать в класс TDateTime, однако выдаёт ошибку о выходе за пределы допустимых интервалов значений.
Код

    unsigned short hour, min, sec, msec;
    unsigned short d, m, y, d2, m2, y2;
    TDateTime t1 = Now();
    Sleep(2000);
    TDateTime t2 = Now();
    TDateTime t3 = t2 - t1;
    // ----
    t1.DecodeDate(&y, &m, &d);
    t2.DecodeDate(&y2, &m2, &d2);
    t3 = EncodeDate(y2 - y, m2 - m, d2 - d); // Project TEST.exe raised exception class EConvertError with message 'Invalid argument to date encode'.
    // ----
    t3.DecodeTime(&hour, &min, &sec, &msec);
    t3.DecodeDate(&y, &m, &d);
....
//#include <SysUtils.hpp>
extern PACKAGE System::TDateTime __fastcall EncodeDate(System::Word Year, System::Word Month, System::Word Day);

- Странность в том, что у функции EncodeDate() типы передаваемых данных WORD/unsigned short: [0..65535];
- разница всех переменных даты даёт результат 0. То есть, вроде всё должно быть нормально, однако на деле вылетает ошибка.


P.S. -> Может снова что-то криво делаю, либо чего-то недопонимаю =(

Это сообщение отредактировал(а) MuForum - 14.9.2009, 08:11


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа!" (Р. Шекли)
PM MAIL WWW ICQ Skype MSN   Вверх
mrbrooks
Дата 14.9.2009, 08:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 167
Всего: 306



MuForum, к сожалению разность дат в VCL сделана мягко говоря, через одно место. Как было верно замечено разность TTime идет корректно, в отличие от TDate. Поэтому можно немного и подмухлевать.

Код

#include <DateUtils.hpp> // DaysBetween;
String GetDifDateTime(TDateTime dt1, TDateTime dt2)
{
    return  String().sprintf(L"%d days ", DaysBetween(dt1,dt2)) + (dt1-dt2).TimeString();
}


Это сообщение отредактировал(а) mrbrooks - 14.9.2009, 08:45
PM MAIL   Вверх
Anikmar
Дата 14.9.2009, 08:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 34
Всего: 59



Help Билдера:
Цитата

The System::TDateTime class inherits a val data member declared as a double that holds the date-time value. The integral part of a System::TDateTime value is the number of days that have passed since 12/30/1899. The fractional part of a System::TDateTime value is the time of day.


Если вы вычитаете даты, то в декодированном виде именно такой результат у вас и должен получится.
Со временем где-то ошибка: секунд должно быть 2.


PM MAIL ICQ   Вверх
mrbrooks
Дата 14.9.2009, 08:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 167
Всего: 306



Цитата(Anikmar @  14.9.2009,  08:50 Найти цитируемый пост)
Если вы вычитаете даты, то в декодированном виде именно такой результат у вас и должен получится.

И это есть нормальная реализация?

Цитата(Anikmar @  14.9.2009,  08:50 Найти цитируемый пост)
Со временем где-то ошибка: секунд должно быть 2.

Это про что?
PM MAIL   Вверх
Anikmar
Дата 14.9.2009, 09:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 34
Всего: 59



Цитата(mrbrooks @  14.9.2009,  08:52 Найти цитируемый пост)
Это про что? 


Цитата(MuForum @  14.9.2009,  07:54 Найти цитируемый пост)
Результаты:
hour = 0;
min = 0;
sec = 0;
msec = 0;
y = 1899;
m = 12;
d = 30;


Это про то, что sec должно быть 2


Цитата(mrbrooks @  14.9.2009,  08:52 Найти цитируемый пост)
И это есть нормальная реализация?

Я не говорил, что это нормальная реализация. Просто она такая. И результат именно тот, который описан в документации.
В результате вычитания 2-х дат получается новая дата, в которой целая часть равна 0.
Целая часть поля val подразумевает количество дней, прошедших с 30 декабря 1899 года 

Как вариант из декодированных лет вычесть 1899, из дней 30 и из месяцев 12, но возможны отрицательные значения - их надо обработать как-то.

На самом деле задача не совсем тривиальная - при большом диапазоне может накопится погрешность за счет високосных годов. Некоторые другие методы работы со временем и датой считают еще хуже.

Для простоты я бы взял такой способ:

Код

    unsigned short hour,min,sec,msec;
    unsigned short d,m,y;    
    TDateTime t1 = Now();
    Sleep(2000);
    TDateTime t2 = Now();
    TDateTime t3 = t2-t1;
    t3.DecodeTime(&hour,&min,&sec,&msec);
    t3.DecodeDate(&y,&m,&d);
  y-=1899;
  m-=12;
  d-=30;
if (d < 0) {d = 30 - d; m--;}
if (m < 0) {m = 12 - m; y--; }


Если я ничего не напутал с минусами/плюсами (что-то не тем сейчас голова занята).
PM MAIL ICQ   Вверх
mrbrooks
Дата 14.9.2009, 09:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 167
Всего: 306



Цитата(Anikmar @  14.9.2009,  09:08 Найти цитируемый пост)
Я не говорил, что это нормальная реализация. Просто она такая. И результат именно тот, который описан в документации.

Я же не с претензией  smile  Я же - обсудить рукоблудие парней их Эмбаркадеро.


Цитата(Anikmar @  14.9.2009,  09:08 Найти цитируемый пост)
Для простоты я бы взял такой способ:

можно. но я бы остановился на своем исходя из условии задачи.  smile 
PM MAIL   Вверх
Anikmar
Дата 14.9.2009, 09:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 34
Всего: 59



Цитата(mrbrooks @  14.9.2009,  09:17 Найти цитируемый пост)
можно. но я бы остановился на своем исходя из условии задачи. 

Само собой. 
Я просто думал, что там еще года и месяцы нужны. Если только дни и время то можно и таким способом.

PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0978 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.