5 use DateTime::Format::Strptime;
 
   7 use SL::Util qw(_hashify);
 
   9 my ($ymd_parser, $ymdhms_parser);
 
  12   my ($class, %params) = @_;
 
  13   return $class->new(hour => 0, minute => 0, second => 0, time_zone => $::locale->get_local_time_zone, %params);
 
  17   return shift->now(time_zone => $::locale->get_local_time_zone);
 
  21   return shift->now(time_zone => $::locale->get_local_time_zone)->truncate(to => 'day');
 
  24 sub to_kivitendo_time {
 
  25   my ($self, %params) = _hashify(1, @_);
 
  26   return $::locale->format_date_object_to_time($self, %params);
 
  30   my ($self, %params) = _hashify(1, @_);
 
  31   return $::locale->format_date_object($self, %params);
 
  40   return $::locale->parse_date_to_object($_[1]);
 
  48 sub add_business_duration {
 
  49   my ($self, %params) = @_;
 
  51   my $abs_days = abs $params{days};
 
  52   my $neg      = $params{days} < 0;
 
  53   my $bweek    = $params{businessweek} || 5;
 
  54   my $weeks    = int ($abs_days / $bweek);
 
  55   my $days     = $abs_days % $bweek;
 
  58     $self->subtract(weeks => $weeks);
 
  59     $self->add(days => 8 - $self->day_of_week) if $self->day_of_week > $bweek;
 
  60     $self->subtract(days => $self->day_of_week > $days ? $days : $days + (7 - $bweek));
 
  62     $self->add(weeks => $weeks);
 
  63     $self->subtract(days => $self->day_of_week - $bweek) if $self->day_of_week > $bweek;
 
  64     $self->add(days => $self->day_of_week + $days <= $bweek ? $days : $days + (7 - $bweek));
 
  70 sub add_businessdays {
 
  71   my ($self, %params) = @_;
 
  73   $self->add_business_duration(%params);
 
  76 sub subtract_businessdays {
 
  77   my ($self, %params) = @_;
 
  81   $self->add_business_duration(%params);
 
  86   return $self->truncate(to => 'month')->add(months => 1)->subtract(days => 1);
 
  90   my ($self, %params) = @_;
 
  92   my $extra_days = $params{extra_days} // 1;
 
  93   $self->add(days => $extra_days);
 
  95   my $day_of_week = $self->day_of_week;
 
  96   $self->add(days => (8 - $day_of_week)) if $day_of_week >= 6;
 
 102   my ($class, $ymd_string) = @_;
 
 105     $ymd_parser = DateTime::Format::Strptime->new(
 
 106       pattern   => '%Y-%m-%d',
 
 112   return $ymd_parser->parse_datetime($ymd_string // '');
 
 116   my ($class, $ymdhms_string) = @_;
 
 118   if (!$ymdhms_parser) {
 
 119     $ymdhms_parser = DateTime::Format::Strptime->new(
 
 120       pattern   => '%Y-%m-%dT%H:%M:%S',
 
 126   $ymdhms_string //= '';
 
 127   $ymdhms_string   =~ s{ }{T};
 
 129   return $ymdhms_parser->parse_datetime($ymdhms_string);
 
 140 SL::Helpers::DateTime - helper functions for L<DateTime>
 
 146 =item C<new_local %params>
 
 148 Returns the time given in C<%params> with the time zone set to the
 
 153 Returns the current time with the time zone set to the local time zone.
 
 157 Returns the current date with the time zone set to the local time zone.
 
 159 =item C<to_kivitendo %param>
 
 161 Formats the date and time according to the current kivitendo user's
 
 162 date format with L<Locale::format_datetime_object>.
 
 164 The legacy name C<to_lxoffice> is still supported.
 
 166 =item C<from_kivitendo $string>
 
 168 Parses a date string formatted in the current kivitendo user's date
 
 169 format and returns an instance of L<DateTime>.
 
 171 Note that only dates can be parsed at the moment, not the time
 
 172 component (as opposed to L<to_kivitendo>).
 
 174 The legacy name C<from_lxoffice> is still supported.
 
 176 =item C<from_ymd $string>
 
 178 Parses a date string in the ISO 8601 format C<YYYY-MM-DD> and returns
 
 179 an instance of L<DateTime>. The time is set to midnight (00:00:00).
 
 181 =item C<from_ymdhms $string>
 
 183 Parses a date/time string in the ISO 8601 format
 
 184 C<YYYY-MM-DDTHH:MM:SS> (a space instead of C<T> is also supported) and
 
 185 returns an instance of L<DateTime>.
 
 187 =item C<end_of_month>
 
 189 Sets the object to the last day of object's month at midnight. Returns
 
 192 =item C<next_workday %params>
 
 194 Sets the object to the next workday. The recognized parameter is:
 
 198 =item * C<extra_days> - optional: If C<extra_days> is given, then
 
 199 that amount of days is added to the objects date and if the resulting
 
 200 date is not a workday, the object is set to the next workday.
 
 205 Returns the object itself.
 
 211 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>