check if date argument is in yyyy-mm-dd format
Solution 1
This will check for the correct format (YYYY-MM-DD) in bash
(with built-in regex match):
if [[ $1 =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]
then echo "Date $1 is in valid format (YYYY-MM-DD)"
else echo "Date $1 is in an invalid format (not YYYY-MM-DD)"
fi
Run:
./script.sh 2015-12-10
Output:
Date 2015-12-10 is in valid format (YYYY-MM-DD)
It doesn't check if the date itself is valid, only the format (as stated in the question, "Check if a date argument is in the correct format (YYYY-MM-DD"))
If you need to check the date format and validate the date value, try something like:
if [[ $1 =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] && date -d "$1" >/dev/null
then echo "Date $1 is valid and matches the format (YYYY-MM-DD)"
fi
This will discard invalid dates like 0000-88-77 that pass the regex matching.
(Credit goes to @glenn jackman for this suggestion.)
Solution 2
You have not tagged an OS, and because you're using ksh
I'm guessing you're probably not using Linux, and you might be using Solaris. The date
command you give will work, but it's for GNU date
where -d
(or --date
) is a GNU enhancement.
So the simple option is to use GNU date
, you may need to install the GNU coreutils package, or you may already have it (check in /usr/sfw/bin
on Solaris) it may already be available possibly as gdate
or gnudate
. This will properly validate the date in the YYYY-MM-DD format (unlike the regex examples elsewhere which will accept
2015-31-01)
You may instead be able to use the touch
command in a similar and more portable (POSIX) way
touch -c -d 2015-12-12T00:00:00 /tmp/does-not-exist
- use
-c
so that a file is not created - append T00:00:00 to the date to make a valid time stamp
(However, if you are using Solaris not only do some versions lack -d
, I have found some versions at least have a bug/misfeature where they do not validate and instead try to be smart, so "2015-02-29" becomes "2015-03-01" with no error, so you cannot use these versions for date validation.)
I prefer this way, it's robust and portable assuming you have gawk
(or mawk
instead, but traditional nawk
lacks these time functions).
#!/usr/local/bin/gawk -f
BEGIN{
split(ARGV[1],bb,/-/)
tm=mktime( bb[1] " " bb[2] " " bb[3] " 00 00 00")
tms=sprintf("%04i-%02i-%02i",bb[1],bb[2],bb[3])
if (tms==strftime("%Y-%m-%d",tm)) exit 0
exit 1
}
The above
- takes the first argument and splits in on the "-" character.
-
mktime()
to determine an epoch time stamp for the indicated YYYY-MM-DD -
sprintf()
to normalise the YYYY-MM-DD (leading 0) -
strftime()
to convert epoch time back to YYYY-MM-DD, and compare as a string
The reason for the extra convert and compare is to catch the case where questionable dates are reinterpreted by the C library mktime()
, as is the case with glibc on linux (the same problem as with Solaris touch
above).
Caring about the correct format of YYYY-MM-DD may or may not mean caring about the validity of the date (something date
will do), and might even mean being able to eliminate YYYY-DD-MM format dates. If you only wish to confirm the format is "date like", then a regular expression will suffice:
grep -qE "^[0-9]{4}-[01]?[0-9]-[0123]?[0-9]$"
grep -qE "^[12][0-9]{3}-(0?[1-9]|10|11|12)-(0?[1-9]|[12][0-9]|3[01])$"
(On Solaris use /usr/xpg4/bin/grep
not the default grep
)
The first one will reject most bogus dates, the second one will reject almost all bogus dates. With -q
there will be no output and you can use the return code as expected. Take care to anchor (^...$
) or otherwise restrict the regular expression so that it does not simply match valid substring, e.g. 2015-12-12345
Related videos on Youtube
ispiro
Updated on September 18, 2022Comments
-
ispiro over 1 year
I want to distribute an application (simple one exe file) so that a user installs it once and it'll be installed for all user accounts on that computer. And it should be done without Wix / InstallShield / Setup-project. (Clickonce doesn’t even support multi-user installations.)
How is it done? Registry edit (Which one?), Manually create an msi file (How? Is there a reference guide for that?)?
Edit
My question is not how to have some command execute at installation time. The question is about how does Windows know which applications are installed.
-
Hamlet Hakobyan about 10 yearsProbably, you must write your own installer.
-
Sinatr about 10 yearsDistribute means installing. If you don't want to use existing installer, then: 1) you can make own installer 2) you can make application what doesn't required installation (could also be portable edition).
-
ispiro about 10 years@Sinatr Not installing would not allow it to be used from the command line, for example.
-
nvoigt about 10 yearsIs there a reason you want to reinvent the wheel instead of using an existing, well tested wheel known to work?
-
Sinatr about 10 yearsBased on question edit, you better explain what you need. Typical installer job is to ensure what software is ready to run. You can make program what will run in any case (even if components are missing, by, to example, using bootstrap) and will configure itself even if started from USB-stick on another PC. If you need something to be available in command line, then your exe-file location has to be in
PATH
or nearcmd.exe
itself. -
ispiro about 10 years@nvoigt Yes. The setup project wheel is unavailable in VS Express, and the other wheels (mostly the highly acclaimed WIX) have a steep learning curve. I agree with this comment .
-
nvoigt about 10 yearsWell, you have to learn something new once in a while. Setup projects were discontinued. Learning to create an MSI faking executable yourself seems silly when you could learn to use WiX (or an alternative, somehow you ruled them all out) instead.
-
-
ispiro about 10 yearsBut what would I put there?
-
Christopher Painter about 10 yearsActually I'd argue that you have the old way and the new way reversed. The old way (1999) was to create a proper installer to do all that. These days all the fresh outs don't have a darn clue how to do that and they reinvent the wheel with new implementations of what you call the "old way".
-
Christopher Painter about 10 years@ispiro- There are "installed" programs. MSI has rich component, feature, product registration metadata that is instrumented through Win32 API and WMI. I can tell you exactly what is installed where in my 300,000 machine environment if you are using a properly authored MSI.
-
clerksx over 8 yearsUsing a regular expression to parse dates is not a good idea. For one, determination of "valid" dates is non-trivial in regular expressions -- ie. determination that 2015-02-31 is not valid, but 2015-03-31 is.
-
X Tian over 8 yearsI understand your point, the question is to validate the format not check whether a date is valid, I think this is a homework assignment, he asked for another way (than using date). :-]
-
Angel Todorov over 8 yearsI would also use
if [[ ... ]] && date -d "$1" >/dev/null
to validate both the format and the actual value -- discard invalid dates like 9999-99-99 that pass the regex matching. -
Dmitry Grigoryev over 8 yearsIf you end up using
date
anyway, why not use the one-liner from the question? -
Cezar Todirisca over 8 years@DmitryGrigoryev Using
date
is not required to check the format. The format is checked withbash
regex matching. Using date additionally validates the value, not format. -
Dmitry Grigoryev over 8 years
date
is not required to check the format, but it can be used check it, so why write a custom regex for something which is already there? -
Cezar Todirisca over 8 yearsI don't think you're checking the input format. You're coercing the format with
date
. The user can supply 20151011 as a value to "$d", and you won't know. -
Cezar Todirisca over 8 years@DmitryGrigoryev See my comment to your answer below.
-
Cezar Todirisca over 8 yearsIt won't be validated, but you won't know why. Maybe because of invalid format (not conforming to YYYY-MM-DD), maybe because of an invalid value (2015-02-31). You will not know. The OP's question was not about value validation, but of format validation. Regarding coercion, I meant
date '+%Y-%m-%d' -d $d
. This does coerce $d to the specified format. -
Dmitry Grigoryev over 8 yearsThe question about format vs. value being incorrect is quite philosophical. For example 2015-13-01 can be both incorrect format (YYYY-DD-MM) or incorrect value (there is no 13-th month). Not only my script will not know why validation failed, but it's simply impossible to know.
-
Faither about 3 yearsWhat if just
^[0-9]{4}-(0?[1-9]|10|11|12)-(0?[1-9]|[12][0-9]|3[01])$
to support years from 0000 to 9999 instead of just1000-2999
? -
mr.spuratic about 3 yearsFeel free, but there are increasingly many bear-traps as you travel back from 1970, so a robust (location aware) time library should be considered for anything better than "date like".