In QML2 I didn\'t find any Calender
control and I have implemented a control which takes date and time as input and I am using the regular expression for the va
Your sequence to match the year is:
([19\s[2-9\s][0-9\s])\d\d
Which looks malformed, as the brackets do not match.
Also, the presence of the two digits (using \d
) means that the expression will not match white space.
So I decided to make a really nice regex that actually works on leap years properly! I then added the rest of the logic you required, and voila, a beauty!
See regex in use here
(?(DEFINE)
(?# Date )
(?# Day ranges )
(?<d_day28>0[1-9]|1\d|2[0-8])
(?<d_day29>0[1-9]|1\d|2\d)
(?<d_day30>0[1-9]|1\d|2\d|30)
(?<d_day31>0[1-9]|1\d|2\d|3[01])
(?# Month specifications )
(?<d_month28>02)
(?<d_month29>02)
(?<d_month30>0[469]|11)
(?<d_month31>0[13578]|1[02])
(?# Year specifications )
(?<d_year>\d+)
(?<d_yearLeap>(?:\d*?(?:(?:(?!00)[02468][048]|[13579][26])|(?:(?:[02468][048]|[13579][26])00))|[48]00|[48])(?=\D))
(?# Valid date formats )
(?<d_format>
(?&d_day28)\/(?&d_month28)\/(?&d_year)|
(?&d_day29)\/(?&d_month29)\/(?&d_yearLeap)|
(?&d_day30)\/(?&d_month30)\/(?&d_year)|
(?&d_day31)\/(?&d_month31)\/(?&d_year)
)
(?# Time )
(?# Time properties )
(?<t_period12>(?i)[ap]m|[ap]\.m\.(?-i))
(?# Hours )
(?<t_hours12>0\d|1[01])
(?<t_hours24>[01]\d|2[0-3])
(?# Minutes )
(?<t_minutes>[0-5]\d)
(?# Seconds )
(?<t_seconds>[0-5]\d)
(?# Milliseconds )
(?<t_milliseconds>\d{3})
(?# Valid time formats )
(?<t_format>
(?&t_hours12):(?&t_minutes):(?&t_seconds)(?:\.(?&t_milliseconds))?\ ?(?&t_period12)|
(?&t_hours24):(?&t_minutes):(?&t_seconds)(?:\.(?&t_milliseconds))?
)
(?# Datetime )
(?<dt_format>(?&d_format)\ (?&t_format))
)
\b(?&dt_format)\b
Or in one line...
See regex in use here
\b(?:(?:0[1-9]|1\d|2[0-8])\/(?:02)\/(?:\d+)|(?:0[1-9]|1\d|2\d)\/(?:02)\/(?:(?:\d*?(?:(?:(?!00)[02468][048]|[13579][26])|(?:(?:[02468][048]|[13579][26])00))|[48]00|[48])(?=\D))|(?:0[1-9]|1\d|2\d|30)\/(?:0[469]|11)\/(?:\d+)|(?:0[1-9]|1\d|2\d|3[01])\/(?:0[13578]|1[02])\/(?:\d+))\ (?:(?:0\d|1[01]):(?:[0-5]\d):(?:[0-5]\d)(?:\.(?:\d{3}))?\ ?(?:(?i)[ap]m|[ap]\.m\.(?-i))|(?:[01]\d|2[0-3]):(?:[0-5]\d):(?:[0-5]\d)(?:\.(?:\d{3}))?)\b
I'll explain the first version as the second version is simply a slimmed down version of it. Note that the regex can easily be changed to accommodate for more formats (only 1 format with slight variations is accepted, but this is a very customizable regex).
01
to 28
01
to 29
01
to 30
01
to 31
02
)02
)04, 06, 09, 11
)01, 03, 05, 07, 08, 10, 12
)\d
)\d*?
(?:(?:(?!00)[02468][048]|[13579][26])|(?:(?:[02468][048]|[13579][26])00))
- Match one of the following(?:(?!00)[02468][048]|[13579][26])
- Match one of the following
02468
, followed by one of 048
, but not 00
13579
, followed by one of 26
(?:(?:[02468][048]|[13579][26])00)
- Match one of the following, followed by 00
02468
, followed by one of 048
13579
, followed by one of 26
[48]00
- Match 400
or 800
[48]
- Match 4
or 8
(?=\D|\b)
- Ensure what follows is either a non-digit character \D
or word boundary character \b
am, pm, a.m, p.m
or their respective uppercase versions (including things such as a.M
where multliple cases are used)00
to 11
00
to 23
00
to 59
00
to 59
000
to 999
)date time
- separation by a space
character)\b(?&dt_format)\b
, which simply matches the dt_format
as specified above, ensuring what precedes and supercedes it is a word boundary character (or no character) \b
To further understand the leap year section of the regex...
I am assuming the following:
4
is 0
) AND (year modulo 100
is not 0
)) OR (year modulo 400
is 0
)The regex works by ensuring:
0, 4, 8
are preceded by a 0, 2, 4, 6, 8
(all of which result in 0
after modulus -> i.e. 24 % 4 = 0
)2, 6
are preceded by a 1, 3, 5, 7, 9
(all of which result in 0
after modulus -> i.e. 32 % 4 = 0
)00
, for 1. and 2., are negated ((?!00)
does this)00
are preceded by 1. and 2. (exactly the same since 4 * 100 = 400
- nothing needs to be changed except the last two digits)400, 800, 4, 8
since they are not satisfied by any of the above conditionsThanks to @sln for the input on the leap year's functionality. The regex below performs slightly faster due to changes provided in the comments of this answer by sln (on a separate question). Changed (?:(?!00)[02468][048]|[13579][26])
to (?:0[48]|[13579][26]|[2468][048])
in the leap year section.
See regex in use here
(?(DEFINE)
(?# Date )
(?# Day ranges )
(?<d_day28>0[1-9]|1\d|2[0-8])
(?<d_day29>0[1-9]|1\d|2\d)
(?<d_day30>0[1-9]|1\d|2\d|30)
(?<d_day31>0[1-9]|1\d|2\d|3[01])
(?# Month specifications )
(?<d_month28>02)
(?<d_month29>02)
(?<d_month30>0[469]|11)
(?<d_month31>0[13578]|1[02])
(?# Year specifications )
(?<d_year>\d+)
(?<d_yearLeap>(?:\d*?(?:(?:0[48]|[13579][26]|[2468][048])|(?:(?:[02468][048]|[13579][26])00))|[48]00|[48])(?=\D|\b))
(?# Valid date formats )
(?<d_format>
(?&d_day28)\/(?&d_month28)\/(?&d_year)|
(?&d_day29)\/(?&d_month29)\/(?&d_yearLeap)|
(?&d_day30)\/(?&d_month30)\/(?&d_year)|
(?&d_day31)\/(?&d_month31)\/(?&d_year)
)
(?# Time )
(?# Time properties )
(?<t_period12>(?i)[ap]m|[ap]\.m\.(?-i))
(?# Hours )
(?<t_hours12>0\d|1[01])
(?<t_hours24>[01]\d|2[0-3])
(?# Minutes )
(?<t_minutes>[0-5]\d)
(?# Seconds )
(?<t_seconds>[0-5]\d)
(?# Milliseconds )
(?<t_milliseconds>\d{3})
(?# Valid time formats )
(?<t_format>
(?&t_hours12):(?&t_minutes):(?&t_seconds)(?:\.(?&t_milliseconds))?\ ?(?&t_period12)|
(?&t_hours24):(?&t_minutes):(?&t_seconds)(?:\.(?&t_milliseconds))?
)
(?# Datetime )
(?<dt_format>(?&d_format)\ (?&t_format))
)
\b(?&dt_format)\b