+sub _make_minutes {
+ my ($package, $attribute) = @_;
+
+ no strict 'refs';
+
+ *{ $package . '::' . $attribute . '_as_hours' } = sub {
+ my ($self, $value) = @_;
+
+ $self->$attribute($value * 60 + ($self->$attribute % 60)) if @_ > 1;
+ return int(($self->$attribute // 0) / 60);
+ };
+
+ *{ $package . '::' . $attribute . '_as_minutes' } = sub {
+ my ($self, $value) = @_;
+
+ $self->$attribute(int($self->$attribute) - (int($self->$attribute) % 60) + ($value // 0)) if @_ > 1;
+ return ($self->$attribute // 0) % 60;
+ };
+
+ *{ $package . '::' . $attribute . '_as_duration_string' } = sub {
+ my ($self, $value) = @_;
+
+ if (@_ > 1) {
+ if (!defined($value) || ($value eq '')) {
+ $self->$attribute(undef);
+ } else {
+ croak $::locale->text("Invalid duration format") if $value !~ m{^(?:(\d*):)?(\d+)$};
+ $self->$attribute(($1 // 0) * 60 + ($2 // 0));
+ }
+ }
+
+ my $as_hours = "${attribute}_as_hours";
+ my $as_minutes = "${attribute}_as_minutes";
+ return defined($self->$attribute) ? sprintf('%d:%02d', $self->$as_hours, $self->$as_minutes) : undef;
+ };
+}
+