How to check the date format using ColdFusion. I want to check that the user enters a date in the format yyyy-mm-dd. When a user enters a date in the format dd-mm-yyyy I want to show an error message. Is there any simple way to solve this?
Do you need to validate the date format from the server side?
Here I've given a simple RegEx check to check the format and did some checks to validate.
<cfset regex = '[0-2][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]'>
<cfset myDate = '2006-12-39'>
<cfset MatchedDate = REMatchNoCase(regex, myDate)>
<cfif arrayLen(MatchedDate) AND isDate(myDate) AND MatchedDate[1] EQ myDate>
Valid date
<cfelse>
Invalid date
</cfif>
As I said in comment, you can validate it on client side with following function
function validateDate(){
var dt = document.forms["Form_Name"]["Date_Field"].value;
var pattern =/^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})$/;
if (dt == null || dt == "" || !pattern.test(dt))
{
alert("invalid date");
return false;
}
else{
return true
}
}
then in cf code, while processing
<cfset desiredFormat=DateFormat(form.Date_Field,"yyyy-mm-dd")>
ps: the js function was taken from Javascript Date Validation ( DD/MM/YYYY) & Age Checking
You could do this:
<cfinput name="StartDate"
validate="date"
type="text"
maxlength="10"
mask="9999-99-99"
message="Start Date must be a valid date."
required="yes">
The key is the mask attribute. However, if you pre-populate this field, attempting to change the value can become frustrating.
Related
I am moving one of our applications from ColdFusion 9.01 to ColdFusion 11 and encountered a situation where I cannot get the date formatted the way I want it using "DateFormat". I read through the docs since things have changed in CF versions, but I honestly can't figure out why this isn't working. It worked beautifully in CF 9. I know it's probably something very easy, but I am just not seeing it.
The query (Oracle DB) provides me a list of the last 30 days and the loop is simply to reformat the date output from "2014-07-01 00:00:00.0" to a more friendly looking display of 01-Jul-2014 except that I cannot get it to format as "dd-mmm-yyyy" it just spits back the original output from the query. I hard coded the date where normally there would be a cfquerparam. Any ideas?
<cfquery name="qryDateArray" datasource="#request.db#">
select trunc(to_date('07/01/2014', 'mm/dd/yyyy') + 1 - rownum) as ref_date
from dual connect by rownum <= 30
</cfquery>
<cfloop from="1" to="#qryDateArray.recordcount#" index="j">
<cfset qryDateArray.ref_date[j] = DateFormat(qryDateArray.ref_date[j], "dd-mmm-yyyy")>
</cfloop>
<cfoutput>
<cfdump var="#qryDateArray#">
</cfoutput>
I could not test this on CF11 since I do not have it handy. I did verify that your code though returns results as you explained when I ran it on my CF10 environment here. So what you can do is add a column to the query object and define it as a varchar and add your formatted data to that. This in turn dumped out the formatted dates.
<cfquery name="qryDateArray" datasource="#request.db#">
select trunc(to_date('07/01/2014', 'mm/dd/yyyy') + 1 - rownum) as ref_date
from dual connect by rownum <= 30
</cfquery>
<cfset aryData = [] />
<cfloop from="1" to="#qryDateArray.recordcount#" index="j">
<cfset ArrayAppend(aryData, DateFormat(qryDateArray.ref_date[j], "dd-mmm-yyyy")) />
</cfloop>
<cfset QueryAddColumn(qryDateArray, "STRDATE", "VarChar", aryData) />
<cfoutput>
<cfdump var="#qryDateArray#">
</cfoutput>
If dependent on the query column names then could use something like Ben's method explained here to do some renaming of the columns: http://www.bennadel.com/blog/357-ask-ben-changing-coldfusion-query-column-names.htm
It'd be great if you'd given us a portable test case rather than one that relies on your database, but I suspect it is because ColdFusion has become more rigid with its type management of query columns.
So CF considers your ref_date column to be of type date, so when you try to put the formatted string back into the query column, CF tries (and succeeds) to convert the string back into a date.
Aside:
I have to wonder why you don't format the data string in the DB from the outset, and just return it the way you need it, rather than returning something else, then looping over the thing to adjust it..?
We receive an XML file with a date node as follows:
<createdDate>1/11/2008 7:04:28 a.m.</createdDate>
Dates are UK format dd/mm/yyy, so 1/11/2008 is 1st November 2008.
We run a coldfusion function to parse the xml and insert into the database. The relevant database field is of datetime datatype and needs to remain that way. How would I format this string representation of the date into a format the database will accept?
Not an ideal situation, but the format you are getting data especially dots in am/pm strings make it hard to read and on top of that it comes in UK Date format. This can help:
<cfset x="21/11/2008 7:04:28 p.m.">
<cfset x=Replace(x,".","","All")>
<cfset y=LSDateFormat(x,"mm/dd/yyyy","English (UK)")>
<cfoutput>
x====#x#
<br/>y===#y#
<cfset z=CreateDateTime(Year(y),month(y),day(y),hour(x),minute(x),second(x))>
z====#z#
<cfset someDatevare=LSParseDateTime(x,"English (UK)")>
</cfoutput>
EDIT As Leigh mentioned, removing periods or any other non-standard characters from the string and then LSParseDateTime will return a date time object.
This is a valid query to return emails surrounded by single quotes from the users table.
SELECT '''' +email + '''' as email
FROM users
where fname = #fname
Yet when I try to do this in a cfscript (cf9) query like this :
var q = new Query(datasource="warewithal");
q.setSQL("SELECT '''' +email + '''' as email
FROM users where firstName= :firstName ");
q.addParam(name="firstName", value=trim(firstName), cfsqltype="cf_sql_varchar");
what I end up with is
Email
+email+
when I expected (and get by running the query in an analyzer)
Email
'bozo#clowns.com'
the cfscript is doing a perserveSingleQuote and not letting me add the single quote to the output.
Is this a bug or what am I doing wrong?
To answer the question in your headline: no, this is not a bug in CFScript. What you are demonstrating has nothing to do with CFScript at all.
However to answer the question you mean to be asking: yes, you have found a bug in Query.cfc.
Here's some code that demonstrates the bug (and demonstrates that it has nothing to do with CFScript, and everything to do with Query.cfc).
This code works fine:
<cfset query = new Query(datasource="scratch_mssql")>
<cfset query.setSql("
SELECT '''' + email + '''' as email
FROM users
WHERE firstName = '#firstName#'
")>
<cfset emailAddresses = query.execute().getResult()>
<cfdump var="#emailAddresses#">
Note that I have hard-coded the filter value into the SQL string. Yuck.
This code errors:
<cfset query = new Query(datasource="scratch_mssql")>
<cfset query.setSql("
SELECT '''' + email + '''' as email
FROM users
WHERE firstName = :firstname
")>
<cfset query.addParam(name="firstname", value=firstName, cfsqltype="CF_SQL_VARCHAR")>
<cfset emailAddresses = query.execute().getResult()>
<cfdump var="#emailAddresses#">
The error for me is:
[Macromedia][SQLServer JDBC Driver][SQLServer]An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements,
look for empty alias names. Aliases defined as "" or [] are not allowed. Change the alias to a valid name.
FYI: The SQL that CF had passed to the DB was:
SELECT '' '' + email + '' '' as email FROM users WHERE firstName = (param 1)
To prove that it's caused by ColdFusion mishandling your single quotes, this works:
<cfset query = new Query(datasource="scratch_mssql")>
<cfset query.setSql("
SELECT email as email
FROM users
WHERE firstName = :firstname
")>
<cfset query.addParam(name="firstname", value=firstName, cfsqltype="CF_SQL_VARCHAR")>
<cfset emailAddresses = query.execute().getResult()>
<cfdump var="#emailAddresses#">
So I'd raise a bug for this if I was you. Note: it's the same on CF9.0.2 and CF10.0.7
But, equally... if I was you I'd not be putting those quotes in there anyhow. Unless there's a very good reason, stick 'em in when you're doing the display, not when you're doing the data processing. I presume they're there for display purposes?
For what it's worth, I just got bit by this issue was well. What seems to work is a simple fix to your Query.cfc object (/[YOUR-CF-INSTALL]/CustomTags/com/adobe/coldfusion/Query.cfc). In the replaceDelimsWithMarkers() function, update this line (LN 341 for me)
newSql = newSql & SINGLEQUOTE & sqlArray[i] & SINGLEQUOTE & " ";
by removing the quoted space at the end, so it is:
newSql = newSql & SINGLEQUOTE & sqlArray[i] & SINGLEQUOTE & "";
Then it works great. I was looking up users, and needed to find one where last name is "O'Neill". No matter what I did I was getting "O' 'Neill" which as you state fails.
Can you think of any cases where this change/fix would have a negative impact? I can't off the top of my head, but for now we are going to copy the query.cfc file, rename it and use it as a custom tag ONLY when we need to run queries where we suspect extra apostrophe's might be used. The only difference will be this one little change.
I have dates as a list in the following format:
09-2012,10-2012,01-2013
What will be the better way to access the minimum and maximum dates from the list?
I'm not really sure which is faster. Here is my list-only-solution below , or you could convert the list to an array and work with that.
This does the job though:
<CFSET dates = "" />
<CFLOOP list="09-2012,10-2012,01-2013" index="date">
<CFSET dates = listappend(dates,DateFormat(createDate(listlast(date,"-"),listfirst(date,"-"),1), "yyyy-mm-dd")) />
</CFLOOP>
<CFSET dates = listsort(dates,"numeric") />
<CFSET min_date = listfirst(dates) />
<CFSET max_date = listlast(dates) />
I would recommend transforming the dates in the list to yyyy-mm-dd.
Then you can just sort the list with ListSort and you will get the first and last date by listfirst and listlast
Similar to Seybsen's answer, only going down the regex path:
<cfscript>
var data = "09-2012,10-2012,01-2013";
data = listSort( reReplace( data, '([0-9][0-9])-([0-9][0-9][0-9][0-9])', '\2-\1', 'all' ), 'numeric', 'asc' );
var minDate = listFirst( data );
var maxDate = listLast( data );
</cfscript>
I adapted #Seybsen's answer to find the max date from a query without doing a query of queries:
<cfset maxCompletedDate = ListLast(ListSort(ValueList(queryName.completedDate), "numeric")) />
Thought I would put this out there if anyone else is looking of the same thing but, again, credit #Seybsen.
BTW, the dates in the database where formatted yyyy-mm-dd H:mm:ss. Timestamps like 2013-09-15 18:43:17
Using CF9 and have a pretty basic html cfgrid that returns results from a SQL query.
There are just two columns in the grid: "ID" and "IDType".
I'm looking to see if there's a way to implement some logic so that when I certain IDType shows up, the value in the ID field becomes the key value in a hyperlink.
Example: IF IDType = "web", and the ID is "1234", the value inside the ID field would show up as http:/www.website.com/1234.html (or...better: just show up as "1234" but be hyperlink-enabled to go to the aforementioned site.)
If the IDType is not (for example) "web", then the value just shows up as a regular cell value (text).
<cfgrid
name="idGrid"
title="Related IDs"
query="get_IDs"
format="html"
>
<cfgridcolumn name="ID" header="ID" />
<cfgridcolumn name="IDType" header="ID Source" />
</cfgrid>
One way to do this is you can generate and append a column to your query using the queryColumnAdd() function, put your link in the cell, and then push the modified query it to the cfgrid.
The link will render and you can click on it!
If I may pseudo code.. first write your normal query
<cfquery name = "myQuery" datasource = "myCFDatasource">
SELECT ID, field1, field2, field3
FROM aTable
</cfquery>
Next, we add your link column onto it..
<cfset queryAddColumn(myQuery, "Link", ArrayNew(1)) />
<cfloop query="myQuery">
<cfset querySetCell(myQuery, "Link", "http://www.mysite.com/some/index.cfm?ID=#myQuery.ID#"), myQuery.currentRow) />
</cfloop>
Then, you can take your modified query myQuery and submit it into your cfgrid like you did above.
Hope that helps get you on the right path.., worked well for me the last time I used it!
You can do it with javascript onRender function.
var gridRender = function()
{
var grid = ColdFusion.Grid.getGridObject('gridname');
var cm = grid.getColumnModel();
cm.setRenderer(0,renderFun); //first arguments stands for column number
}
var renderFun = function(value, cellMeta, record, row, col, data)
{
if(value != null)
{
switch(col)
{
case 0:
return "<a href='yoururl?id=" & value & "'>" & value & "</a>";
default:
return value;
}
}
};
And on coldfusion page call gridRender function on ajaxonload
<cfset ajaxOnLoad("gridRender")>
ajaxOnLoad will automatically call gridRender js function on page loaded and setup grid to render through gridRender function. renderFun will call everytime your column cell going to render.
Note: I haven't tested code just consider as test code and modify as per your need.