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>