in reply to Detecting whether DateTime object has a time component or not?

I believe DateTime objects always represent valid points in time (for example, this FAQ says "DateTime objects represent exact instants in time (down to the nanosecond resolution)"), and so don't have a concept of "this field isn't set" (with the exception of the time zone, where the "floating" zone is kind of like "unset").

I am checking at a position where the date has been converted to DateTime object.

No chance you can do this before? Update: What I'm saying is that it'd probably be best if you apply these defaults yourself, sometime between where the user enters the data, like detecting the difference between "2017-06-16" and "2017-06-16T00:00:00", or applying the defaults just before you create the DateTime object.

Update 2: Another thought: I am guessing that this is some kind of system where you are asking the user to enter a date and optionally time for the end of some period, and if the user only enters a date then you assume it's the end of the day on that date? You could adjust the user interface to be more in line with the concept that the period ends at an exact time, like defaulting the user input mask to 23:59:59, or perhaps adding a radio button that makes the input look something roughly like "End Time: __/__/____ (x) at the end of this day (midnight) or ( ) on this day at this time: __:__:__".

Replies are listed 'Best First'.
Re^2: Detecting whether DateTime object has a time component or not? (updated)
by perlancar (Hermit) on Jun 16, 2017 at 10:17 UTC

    Yup, I ended up looking at the original data, which fortunately are also available. It's a CLI where user can specify the argument YYYYMMDD or YYYYMMDDTHH:MM:SS which will be coerced by the CLI framework into a DateTime before being passed to the subroutine. The coercion might be able to accept 'today' (no time-of-day elements) or 'now' (has time-of-day elements) or other formats in the future, but I think I'm okay for now, thanks.

      Yup, I ended up looking at the original data, which fortunately are also available.

      That's good! Here's how I might have done it:

      use warnings; use strict; use DateTime::Format::Strptime; my $strp = DateTime::Format::Strptime->new(on_error=>'croak', pattern=>'%Y%m%dT%H:%M:%S', time_zone=>'UTC'); while (<DATA>) { chomp; my $dt; if ($_ eq 'today') { $dt = DateTime->now->truncate( to => 'day' ) ->set( hour=>23, minute=>59, second=>59 ) } elsif ($_ eq 'now') { $dt = DateTime->now } else { $_ .= "T23:59:59" if /^\d{8}$/; $dt = $strp->parse_datetime($_) } print "$_ => ",$dt->strftime('%Y-%m-%d %H:%M:%S %Z'),"\n"; } __DATA__ 20170616T15:30:53 20170616 now today