Nano Hash - криптовалюты, майнинг, программирование

perl вычесть один месяц из даты

Я получаю даты в формате %dd.%mm.%YYYY и пытаюсь вычесть один месяц, используя Perl.

примеры: 12.07.2013 -> 12.06.2013 , 30.09.2013 -> 31.08.2013

Должен ли я использовать Date:: Calc? Любые идеи?

Спасибо

10.09.2013

  • Вычитание одного месяца из 30 сентября и окончание 31 августа было бы необычным для общего сокращения на один месяц (хотя обратный сценарий, включающий один месяц с 31 июля и заканчивающийся 30 июня, будет считаться нормальный). Вы уверены, что это то, что нужно? Пожалуйста, предоставьте еще пару примеров и любой код Perl, который вы пробовали до сих пор. 10.09.2013

Ответы:


1

Вы можете использовать Time::Piece, который является основным модулем, начиная с Perl версии 5.9.5.

use strict;
use warnings;
use Time::Piece;
use Time::Seconds;

my $t = Time::Piece->strptime(shift, "%d.%m.%Y");
$t -= ONE_MONTH;
print $t->strftime("%d.%m.%Y");

Учитывая аргументы 12.07.2013 и 30.09.2013, этот код печатает 11.06.2013 и 30.08.2013 соответственно.

Функция strptime анализирует строку в соответствии с шаблоном в объект Time::Piece. Затем мы можем просто добавить/вычесть объект, чтобы управлять датой. Здесь я использую константу из модуля Time::Seconds, соответствующую одному месяцу.

Все это взято из документации для Time::Piece.

10.09.2013
  • 12.07.2013 минус ONE_MONTH равняется 11.06.2013 этим методом. Очевидно, что многое зависит от определения одного месяца в OP, но я ожидаю, что из примеров до сих пор мы говорим о расчетах календарного месяца, а не о фиксированном количестве дней (или секунд). 10.09.2013
  • Time::Piece имеет метод add_months, который даст здесь 12.06.2013 (при использовании с -1 в качестве аргумента). Тем не менее, все еще интересно, что ожидает ОП, если результатом операции будут невозможные даты, например. 30.02.2013. 10.09.2013
  • @SlavenRezic add_months, похоже, ничего не делает, просто выдает ту же дату. Возможно, это немного неправильная функция в модуле. 10.09.2013
  • Результатом perl -MTime::Piece -e 'warn Time::Piece->new->add_months(-1)' является Sat Aug 10 14:44:56 2013 at -e line 1.. Сегодня 2013-09-10, так что здесь все в порядке; тот же результат с perl 5.10.1 и 5.18.1, вероятно, здесь установлен Time::Piece по умолчанию. 10.09.2013
  • @SlavenRezic Ага, понятно. По какой-то странной причине он возвращает только обработанный объект и не влияет на исходный объект. Так что я должен был бы сделать my $t2 = $t->add_months(-1). Ну это как минимум оригинально. Попробуйте perl -MTime::Piece -lwe'$t = localtime; $t->add_months(-1); print $t;' 10.09.2013
  • Я бы не сказал, что это оригинально, это просто функционально. 10.09.2013
  • Предупреждение: действительно можно получить странное поведение, как и обещано в документации. Месячный отпуск с 03-31 дает мне 03-03: perl -MTime::Piece -wE'$d=shift//20190331; $dt = Time::Piece->strptime($d, "%Y%m%d"); say $dt; say $dt->add_months(-1)' (и я также могу сделать так, чтобы он давал мне 02-01, в зависимости от того, как установлена ​​дата). Использование ONE_MONTH намного хуже: добавление месяца к 05-01 таким образом дает мне 05-31: perl -MTime::Piece -MTime::Seconds -wE'$d=shift//20190501; $dt = Time::Piece->strptime($d, "%Y%m%d"); say $dt; say $dt + ONE_MONTH'. Теперь я использую Time::Piece, но он у меня завернут. 13.04.2019
  • [продолжает] И эти даты не являются уникальными случаями, и сюрпризы также непостоянны. Возьмите месячный отпуск 07-31 (используя add_month(-1), первую строчку выше), и мы получим 07-01, но если вместо этого использовать - ONE_MONTH, мы получим 06-30. Так что в данном случае именно ONE_MONTH дает разумное поведение. 13.04.2019

  • 2

    DateTime поддерживает привязку к поведению в конце месяца, которое вы ищете. Параметр end_of_month описан в разделе Добавление длительности к дате и времени. Я также предоставил решение для Date::Calc, которое показывает логику. Результат одинаков для обоих решений.

    Дата и время:

    use DateTime;
    
    my @dates = qw(
        01.01.2013
        28.02.2013
        12.07.2013
        30.09.2013
    );
    
    foreach my $string (@dates) {
        my %p; @p{qw(day month year)} = split /\./, $string;
        my $dt = DateTime->new(%p);
        for my $n (-1, 1) {
            my $res = $dt->clone->add(months => $n, end_of_month => 'preserve');
            printf "%s %+d month => %s\n", $string, $n, $res->strftime('%d.%m.%Y');
        }
    }
    

    Дата::Расчет:

    use Date::Calc qw[Days_in_Month Decode_Date_EU];
    
    my @dates = qw(
        01.01.2013
        28.02.2013
        12.07.2013
        30.09.2013
    );
    
    sub Add_Months {
        @_ == 4 || die q/Usage: Add_Months($year, $month, $day, $delta)/;
        my ($y, $m, $d, $delta) = @_;
    
        my $ultimo = ($d == Days_in_Month($y, $m));
    
        use integer;
        $m += $delta;
        $y += $m / 12;
        $m %= 12;
        if ($m < 1) {
            $y--, $m += 12;
        }
        my $dim = Days_in_Month($y, $m);
        if ($d > $dim || $ultimo) {
            $d = $dim;
        }
        return ($y, $m, $d);
    }
    
    foreach my $string (@dates) {
        for my $n (-1, 1) {
            printf "%s %+d month => %.2d.%.2d.%.4d\n",
                $string, $n, reverse(Add_Months(Decode_Date_EU($string), $n));
        }
    }
    

    Выход:

    01.01.2013 -1 month => 01.12.2012
    01.01.2013 +1 month => 01.02.2013
    28.02.2013 -1 month => 31.01.2013
    28.02.2013 +1 month => 31.03.2013
    12.07.2013 -1 month => 12.06.2013
    12.07.2013 +1 month => 12.08.2013
    30.09.2013 -1 month => 31.08.2013
    30.09.2013 +1 month => 31.10.2013
    
    25.09.2013
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..