Сравнивать две даты в формате дд/мм/гггг

 
0
 
Perl
ava
Suppir | 10.04.2013, 11:18
Нужно сравнивать две даты в формате дд/мм/гггг и определить, какая дата больше.
День и месяц может быть записан с нулем или без нуля:  01/01/2013 или 1/1/2013.

Как это проще всего сделать?
Comments (15)
ava
reiserford | 10.04.2013, 10:51 #
разбей каждую до DD, MM, YYYY
каждой сделай sprintf('%04d-%02d-%02d', YYYY, MM, DD) и сравни результаты sprintf
ava
Poseidon | 10.04.2013, 10:53 #
Формат похож на используемый в Англии и для британских Windows подойдет обычный StrToDate. Но для не британский будет выдавать ошибку. Так что нужно силой указать сепаратор (в русских Windows это точка).


var
   myDate : TDate;
begin
   DateSeparator:= '/';
   myDate := StrToDate('15/03/75');
end;

Ну а TDate - это обычный Double и сравнивается операторами сравнения.
ava
Suppir | 10.04.2013, 11:07 #
Ребята, как думаете, а такой вариант сработает?


$days = $y * 356 + ($m - 1) * 30 + $d;


То есть я просто получаю количество дней, умножая год на 356, месяц - на 30 и прибавляя дни. А потом просто сравниваю количество дней в двух датах.
ava
Jimy | 10.04.2013, 12:13 #
Не сработает. 31 января и 1 февраля дадут одинаковое значение.
ava
DProf | 10.04.2013, 13:48 (Edited 10.04.2013 14:52) #
Вот функция на С для нахождения юлианской даты. Можете переработать, убрать время (Вам оно не надо как я понял) и сравнивать.

/*  finds the julian date (itsJDay) given the year, month, day, and time.
*  the julian date is defined by each elapsed day since noon, jan 1, 4713 bc.
*
*  algorithm     : calculate the answer in one step for efficiency
*
*  inputs          description                    range / units
*    year        - year                           1900 .. 2100
*    mon         - month                          1 .. 12
*    day         - day                            1 .. 28,29,30,31
*    hr          - universal time hour            0 .. 23
*    min         - universal time min             0 .. 59
*    sec         - universal time sec             0.0 .. 59.999
*
*  outputs       :
*    jd          - julian date                    days from 4713 bc
* --------------------------------------------------------------------------- */
double jday()
{
    double JDay = 367.0 * Year -
        floor((7 * (Year + floor((Month + 9) / 12.0))) * 0.25) +
        floor( 275 * Month / 9.0 ) +
        Day + 1721013.5 +
        ((Sec / 60.0 + Min) / 60.0 + Hour) / 24.0;  // ut in days
        // - 0.5*sgn(100.0*year + mon - 190002.5) + 0.5;
    return JDay;
}  // end jday

31 января и 1 февраля сортируются без проблем
ava
Suppir | 10.04.2013, 15:29 #
Только эти два дня?
ava
arto | 10.04.2013, 16:19 #
формула вычисления високосных годов известна -- написать функцию не проблема подсчета дней не проблема, imho.
ava
Suppir | 10.04.2013, 16:35 #
В общем, определяю так:


sprintf '%04d/%02d/%02d', $y+1900, $m+1, $d;


а потом сравниваю оператором gt. 
ava
krypt3r | 11.04.2013, 06:02 #
1. Заюзать Delta_Days из Date::Calc
2. Перевести даты в Unixtime или Julian Day и сравнивать
ava
Pfailed | 11.04.2013, 13:36 #
POSIX::mktime
ava
DProf | 11.04.2013, 16:09 (Edited 11.04.2013 17:16) #
 
ava
DProf | 11.04.2013, 16:14 (Edited 11.04.2013 17:28) #
Сравнивать строки - плохо. Чего Вам функция вычисления вычисления юлианского дня не понравилась? Если что, то это количество дней (дробное), прошедшее с 4713 года до нэ. Это уникальное значение. В *NIX время практически так же хранится.
Самому функцию писать не надо даже, если не хотите. Юзайте так:

use Time::JulianDay;
 $jd = julian_day($year, $month_1_to_12, $day);

Сравнить то есть так:

my $JD_1 = julian_day($year_1, $month_1, $day_1);
my $JD_2 = julian_day($year_2, $month_2, $day_2);

if ($JD_1 > $JD_2)
{#data_1 more than data_2
}
else
{#data_2 more than data_1
}


Но поскольку Вы модулей использовать не хотите - то пишите julian_day() сами по аналогу с функцией на С что я скинул
ava
Suppir | 15.04.2013, 08:58 #
Понятно, спасибо.

Дело не в том, что "не хочу использовать модули". Просто у пользователей - целый зоопарк из разных версий Perl. Нужного модуля может и не быть, а  почти никто не умеет их специально устанавливать. Поэтому приходится писать так, чтобы скрипт работал на любой сборке Perl 5.8 или выше. 
ava
arto | 15.04.2013, 09:23 #
# corelist -a Time::Local | grep -v undef | head -7
Data for 2013-03-21
Time::Local was first released with perl 5
  v5.7.3     1.04      
  v5.8.0     1.04      
  v5.8.1     1.07      
  v5.8.2     1.07      
# corelist -a POSIX | grep -v undef | head -7
Data for 2013-03-21
POSIX was first released with perl 5
  5.002      1.00      
  5.00307    1.00      
  5.004      1.02      
  5.00405    1.02      
#
ava
Pilat66 | 04.05.2013, 08:34 #
Цитата (reiserford @  10.4.2013,  10:51 findReferencedText)
разбей каждую до DD, MM, YYYY

каждой сделай sprintf('%04d-%02d-%02d', YYYY, MM, DD) и сравни результаты sprintf 


В первом ответе есть совет, может быть без юлианских календарей и високосных секунд будет проще?

#!perl    
use strict;

sub normalize {
    warn $_[0];
    my $t = sprintf('%04d-%02d-%02d', reverse(split '/', $_[0]));
    warn $t;
    return $t;
}

my $date1 = '01/01/2012';
my $date2 = '2/2/2012';

print "date1 < date2" if normalize($date1) lt normalize($date2);
Please register or login to write.
Firm of day
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Contributors
advanced
Submit