Why does CDate("0/5/14") return 5/14/2000? - vba

In Excel 2010 VBA, I'm testing to make sure my code handles invalid user input correctly. I'm using CDate to validate date inputs. I've found that with the invalid date input "0/5/14", CDate returns the date 5/14/2000.
Is that a CDate bug, or am I missing something? In an Excel worksheet cell, "0/5/14" does not evaluate to a date.
Similarly, Year("0/5/14") in Excel VBA returns 2000, while =Year("0/5/14") in an Excel worksheet cell returns an error.
Windows regional settings are English USA, so month/day/year is standard.

The CDate function (and other string-to-date functions such as DateValue) examines a string representation of a date and attempts to match it to any known date format, considering it to be a valid date unless it cannot be made to match any of the known formats. Since it can be the case that years can be expressed as 1 or more digits, the input string "0/5/14" can be considered to be in year/month/day format, so it returns "14th of May, 2000" in your local date format.
The difference between CDate and DateValue is that CDate can accept a number, while DateValue cannot. Both use the PC's Short Date format first - not that that would matter for someone using en-US settings. Both functions fall back to other date formats if the supplied string doesn't fit on the first attempt.
It is up to you how you handle such situations. It may well be that in your situation, a date in year 2000 would be out-of-range, so you could reject it on that basis. If you want to insist on "mm/dd/yyyy" format, you could write your own parser code.

I believe #Borja Güiles Quintana had the correct answer with basically it's reading it as YY/MM/DD. CDate does not exist as a worksheet function so it does not surprise me that the sheet (as opposed to VBA) interpretation differs (would not be the first time, eg TRIM).
Any year (and which part represents year may be system dependent) is interpreted according to rules (that may be version dependent) but for Excel 2013 and two-digit values these stop at 29 for this century - ie 30 is interpreted as 19 30. More details of that here.

Related

Dates imported from excel documents were stored as integers

Dates entered in the "short date" format in Excel were imported differently into OpenRefine. For example, 8/30/2019 in Excel became Fri Aug 30 00:00:00 EDT 2019 in OpenRefine. I would like to get them back to a short date (mm/dd/yyyy) or even a string (mmddyyyy) format, with no day of week, time, or time zone data retained. I've been trying to transform them but can't figure out the grel code.
The toString() function takes an optional format string that you can use for this. You can use value.toString('M/d/y') (or toString(value,'M/d/y'))to get a string in the format of your first example. Note, however, that once you convert it to a string you'll lose the ability to use any of the date related functions like calculating how far apart two dates are.

vba access Dlookup with dates in dd/mm/yyyy forma

I'm trying to get a value using a DlookUp, the problem is access formats my dd/mm/yyyy into mm/dd/yyyy despite using the Format function.
muestraAguasDatos = Nz(DLookup("[name]", "samples", "[location] = '" & location & "' AND ([name] LIKE
'*ACRT*' OR [nombre] LIKE '*CAWQ*') AND [sample_date] = #" & Format(sampleDate, "dd/mm/yyyy") & "#"))
This DLookup works when day value are > 12 but when it's lower and despite having the format it still format it to mm/dd/yyyy
Can you help me solving this issue please?
There are so many misunderstanding with MS Access date fields for non-US residents.
The basic rule is :
Whenever you specify a hardcoded date literal using #the date# notation, in
either :
an SQL query
a query filter criteria
in VBA
in a Dlookup() like you do
You should ALWAYS use the US date format : MM/DD/YYYY, or the ISO format YYYY/MM/DD
The confusion among Access beginners, comes from several things :
In the interfaces, by default, MS Access does an implicit conversion of the dates in the format that is defined on Windows Regional and Language Options setting of the computer. So non-US residents might have the impression that dates are always stored by default in the DD/MM/YYYY format, but that cake is a lie. Dates are stored as numbers, and it is just the display format that changes and is adapted following the computer settings.
In some cases, when you code date literals with #the date# in VBA or a Query, using DD/MM/YYYY format, it just works fine. The reason is date there's a check date algorithm in MS Office that validates a date and modify it to the right format in certain circumstances:
When your date begins by the year, MS Access is smart enough to detect it and it will then consider that your date is enterred in YYYY-MM-DD and do an implicit convertion to MM/DD/YYYY.
If the month part is higher than 12 and lower then 31, then MS Access will understand that this is in fact a DAY, and that you hardcoded the month at the other place. So for instance if you introduce 15th of September like this : #15/09/2019# it will implicitly be transformed in #09/15/2019#. However if you enters the 11th September like this #11/09/2019#, then Access will process it as 09th November !!!
Personal opinion, I have always found this last behavior plain stupid, because it may introduces a lot of troubles on applications of people not acquainted by that mechanism, and that tracking where the problems comes can be very tedious. It's sneaky, it should not be there. Much better to raise an error if the format is wrong.

DATEDIFF working on yyyymmdd format SQL server

Why the DATEDIFF accepts yyyymmdd format ? Isnt it only for yyyy-mm-dd format ?
The function DATEDIFF(datepart, start_date, end_date) is working fine when the dates are in yyyymmdd format e.g.
DATEDIFF(DAY, 20161201, 20161231);
It gives answer 30
and if you do DATEDIFF(DAY, 20161201, 20161231) + 1 -- end date inclusive
It gives 31
Thanks,
Aiden
This can be a bit hard to tease out, but it is explained in the documentation, in the section "Supported String Literal Formats for date".
There are five sections on this (but the last two are API specific). The first section is affected by internationalization settings and has a bunch of different formats.
The second is the ISO 8601 format. I think the hyphenated format conflicts with the very last format in the first table ("yyyy dd mm" without the hyphens).
The final section has this informative line "A six- or eight-digit string is always interpreted as ymd". Hence, 'YYYYMMDD' is always interpreted correctly. Hence, this is the unambiguous format for date/time.
Note: Because the functions you are using expect dates, if the integer works, then it is converted to a date using its string representation. Normally, date constants should be in single quotes.
Actually its the sql server default format of dates but you can format your dates according to your requirements by following the link:
http://www.sql-server-helper.com/sql-server-2012/format-function-vs-convert-function.aspx

Formatting Date according to regional settings in VBA

I am extracting several dates from an e-mail body.
It is random, so it could be a date in English, Spanish or some other format.
I need to get this date and convert it to the user's profile date settings.
E.g: **User profile is English language**
I receive 15/jun/2015 or 15-junio-2015 or 15/06/2015
The output jun/15/2015 or june-15-2015 or 06/15/2015
What would be the easiest way to do such task?
Thanks.
You may find the Format functon available in VBA helpful. But I think it may not help in case of other languages, you will need to use the DateValue function which returns a Date value containing the date information represented by a string, with the time information set to midnight (00:00:00).

SQL - Comparing between Dates in WHERE Statement not work correctly in Access DB

I am trying to compare between two Dates in my SQL statement. The date format I use in my DataBase is DD/MM/YYYY.
When I write the following sql:
SELECT * FROM [MyTableName]
WHERE #03/10/2014# >= #02/11/2014#;
The result of the WHERE statement is True - (Not Good).
According to the format I wanted (DD/MM/YYYY) it should be False, But in the SQL Statement it appears in a MM/DD/YYYY format.
The same problem was appeared when I used the Now() Function:
WHERE NOW() >= #02/12/2014#;
(Today is the 03/11/2014)
It should be False because 11 < 12 but still the statement is True. (The SQL using the MM/DD/YYYY format).
So I Added a FORMAT function and now it looks like that:
WHERE FORMAT(#03/10/2014#, 'DD/MM/YYYY') >= FORMAT(#02/11/2014#, 'DD/MM/YYYY');
This time the result of the WHERE statement is Flase - (Good!).
So far the Format function looks like a good solution, BUT when trying to reformat the NOW() Date, the problem is appearing again:
This WHERE statement should be True
WHERE FORMAT(NOW(), 'DD/MM/YYYY') = FORMAT(#03/11/2014#, 'DD/MM/YYYY');
But it is False
While this WHERE statement should be False
WHERE FORMAT(NOW(), 'DD/MM/YYYY') = FORMAT(#11/03/2014#, 'DD/MM/YYYY');
And it is True
(Today is the 03/11/2014)
We can see that the Format function not working correctly on the NOW() Date.
Is someone have a solution for that?
Date literals, as delimited with # characters, will usually interpret values of the form NN/NN/NNNN in MM/DD/YYYY format - regardless of your culture settings.
In some cases, such as when the first set of digits is > 12, the environment may choose to interpret the value in DD/MM/YYYY order just to handle the input, but this is non-standard behavior that you should not rely upon.
Specifically, MSDN documentation for the VB Date Data Type says the following:
You must enclose a Date literal within number signs (# #). You must specify the date value in the format M/d/yyyy, for example #5/31/1993#. This requirement is independent of your locale and your computer's date and time format settings.
The reason for this restriction is that the meaning of your code should never change depending on the locale in which your application is running. Suppose you hard-code a Date literal of #3/4/1998# and intend it to mean March 4, 1998. In a locale that uses mm/dd/yyyy, 3/4/1998 compiles as you intend. But suppose you deploy your application in many countries. In a locale that uses dd/mm/yyyy, your hard-coded literal would compile to April 3, 1998. In a locale that uses yyyy/mm/dd, the literal would be invalid (April 1998, 0003) and cause a compiler error.
This is true for VB, as well as VBA and MS Access.
One way to work around this is to not use a date literal. Instead, consider using the DateValue function to parse the string to a date object before querying with it.