Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Сравнивать две даты в формате дд/мм/гггг


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

Как это проще всего сделать?

Добавлено через 8 минут и 30 секунд
Без модулей.

Автор: reiserford 10.4.2013, 10:51
разбей каждую до DD, MM, YYYY
каждой сделай sprintf('%04d-%02d-%02d', YYYY, MM, DD) и сравни результаты sprintf

Автор: Poseidon 10.4.2013, 10:53
Формат похож на используемый в Англии и для британских Windows подойдет обычный StrToDate. Но для не британский будет выдавать ошибку. Так что нужно силой указать сепаратор (в русских Windows это точка).

Код

var
   myDate : TDate;
 begin
   DateSeparator:= '/';
   myDate := StrToDate('01/01/2013');
end;

Ну а TDate - это обычный Double и сравнивается операторами сравнения.

Добавлено через 4 минуты и 35 секунд
Ой, сори ребята, разделом уж сильно ошибся smile

Автор: Suppir 10.4.2013, 11:07
Ребята, как думаете, а такой вариант сработает?

Код

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


То есть я просто получаю количество дней, умножая год на 356, месяц - на 30 и прибавляя дни. А потом просто сравниваю количество дней в двух датах.

Автор: Jimy 10.4.2013, 12:13
Не сработает. 31 января и 1 февраля дадут одинаковое значение.

Автор: Suppir 10.4.2013, 15:29
Только эти два дня?

Добавлено через 1 минуту и 34 секунды
Да, посчитал - в каждом месяце такая фигня выходит...

Автор: arto 10.4.2013, 16:19
формула вычисления високосных годов известна -- написать функцию не проблема подсчета дней не проблема, imho.

Автор: Suppir 10.4.2013, 16:35
В общем, определяю так:

Код

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


а потом сравниваю оператором gt. 

Автор: krypt3r 11.4.2013, 06:02
1. Заюзать Delta_Days из Date::Calc
2. Перевести даты в Unixtime или Julian Day и сравнивать

Автор: Pfailed 11.4.2013, 13:36
POSIX::mktime

Автор: DProf 11.4.2013, 16:14
Сравнивать строки - плохо. Чего Вам функция вычисления вычисления юлианского дня не понравилась? Если что, то это количество дней (дробное), прошедшее с 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
}


Читать
 http://perldoc.perl.org/5.10.1/perlfaq4.html#How-can-I-find-the-Julian-Day%3f
 http://search.cpan.org/~muir/Time-modules-2011.0517/lib/Time/JulianDay.pm
Но поскольку Вы модулей использовать не хотите - то пишите julian_day() сами по аналогу с функцией на С что я скинул

Автор: Suppir 15.4.2013, 08:58
Понятно, спасибо. 

Дело не в том, что "не хочу использовать модули". Просто у пользователей - целый зоопарк из разных версий Perl. Нужного модуля может и не быть, а  почти никто не умеет их специально устанавливать. Поэтому приходится писать так, чтобы скрипт работал на любой сборке Perl 5.8 или выше. 

Автор: arto 15.4.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      
#

Автор: Pilat66 4.5.2013, 08:34
Цитата(reiserford @  10.4.2013,  10:51 Найти цитируемый пост)
разбей каждую до 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);

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)