Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validate if a string matches a format string

In Ruby, you can parse a string into a DateTime based on a given format string, for example:

3.2.4 :001 > DateTime.strptime(Time.now.to_s, '%Y-%m-%d %H:%M')
Sat, 17 Aug 2024 13:31:00 +0000
3.2.4 :002 > Time.now.to_s
"2024-08-17 13:31:52 -0400"

Notice how strptime works even if the current time is more detailed than '%Y-%m-%d %H:%M', which doesn't have seconds or timezone in it.

What I'd like to have is a way to validate a string like '2024-08-15 08:00' actually conforms to a format.

I know that you can use a regex to validate something like this, but I'd prefer something that could check for a datetime format string without necessarily even parsing.

My preference here is because %Y-%m-%d %H:%M looks cleaner than /\A\d{4}-\d{2}-\d{2} \d{2}:\d{2}\z/ (also, if it happens to validate that it's a real datetime rather than 9999-99-99 99:99 that's a bonus, though it would be helpful either way).

like image 958
bgcode Avatar asked Oct 30 '25 00:10

bgcode


1 Answers

Searching through Ruby's strptime implementation, I found DateTime::_strptime (it is publicly documented but starts with _ for some reason) which returns a Hash that contains a :leftover string containing the trailing part of the string that was skipped.

If the string is consumed completely, the key does not exist in the returned hash. If the parsing fails, the function returns nil.

require "date"

def strptime?(format, input)
  if (hash = DateTime._strptime(format, input))
    !hash.key?(:leftover)
  else
    false
  end
end

p strptime?(Time.now.to_s, "%Y-%m-%d %H:%M")
p strptime?(Time.now.to_s[..14], "%Y-%m-%d %H:%M")
p strptime?(Time.now.to_s[..15], "%Y-%m-%d %H:%M")
p strptime?(Time.now.to_s[..16], "%Y-%m-%d %H:%M")
p strptime?("", "%Y-%m-%d %H:%M")

Output:

false
true
true
false
false
like image 110
Dogbert Avatar answered Oct 31 '25 18:10

Dogbert



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!