Consider the following date entries. I want DD/MM/YYYY format for both input strings and output strings
<cfset SetLocale('indonesian') /> <!--- also set in Railo Admin --->
<cfdump var="#GetLocale()#" />
<cfdump var="#LSDateFormat('01/07/2014', 'dd/mm/yyy')#" />
<cfdump var="#LSDateFormat('31/07/2014', 'dd/mm/yyy')#" />
<cfdump var="#LSDateFormat(Now())#" />
Output:
string in <--- correct for 'indonesian'?
string 07/01/2014 <--- wrong
string 31/07/2014 <--- correct... maybe
string 31/07/2014 <--- correct... maybe
Indonesia uses DD/MM/YYYY format but Railo seems to treat the date input string as a U.S. date unless it's "invalid" (U.S. month higher than 12).
The OS locale is: LC_TIME="en_AU.UTF-8" (Australian). This locale also uses DD/MM/YYYY
So given that nothing I can see specifies a US date format and I'm using the LS variant of the function why are my date input strings being interpreted as U.S. dates?
Actually I really don't like the DD/MM changing locale based on the MM value. I'm looking for an answer that actually validates the date is DD/MM/YYYY as well (preferably using something built-in rather than a UDF).
The issue is that the date passed to lsDateFormat function is expected to be a date object. If you pass in a string coldfusion will try to convert the string into a date object for you. This automatic conversion will do this assuming the american date format.
You can test this by creating your date with the createDate function. You could quickly build your own date parsing function a sample I hacked together is found below:
NOTE: In a complete solution you will have to check if the response from the function is a unknown date and act accordingly.
<cfset SetLocale('indonesian') /> <!--- also set in Railo Admin --->
<cfdump var="#GetLocale()#" />
<cfdump var="#LSDateFormat('01/07/2014', 'dd/mm/yyy')#" />
<cfdump var="#LSDateFormat('31/07/2014', 'dd/mm/yyy')#" />
<cfdump var="#LSDateFormat(Now())#" />
<!--- Now with creating date objects--->
<cfdump var="#LSDateFormat(createDate(2014,07,01), 'dd/mm/yyy')#" />
<!--- Using our own date parser--->
<cfdump var="#LSDateFormat(udf_parseDate('01/07/2014'), 'dd/mm/yyyy')#" />
<cfdump var="#LSDateFormat(udf_parseDate('31/07/2014'), 'dd/mm/yyyy')#" />
<cffunction name="udf_parseDate" output="false" returntype="date">
<cfargument name="value" required="true" type="string">
<cfset var UNKNOWN_DATE = createDate(1900,1,1)>
<cfset var DELIMITER = "/">
<cfset var iDay = 0>
<cfset var iMonth = 0>
<cfset var iYear = 0>
<cftry>
<cfset iDay = getToken(arguments.value,1,DELIMITER)>
<cfset iMonth = getToken(arguments.value,2,DELIMITER)>
<cfset iYear = getToken(arguments.value,3,DELIMITER)>
<cfset tmp = createDate(iYear,iMonth,iDay)>
<cfcatch type="any">
<cfreturn UNKNOWN_DATE>
</cfcatch>
</cftry>
<cfreturn tmp>
</cffunction>
My advice would be to stay away from all the inbuild localisation features they more often then not don't work the way that one needs them to work in a fully localised application. especially if you need to support multiple locales at the same time. e.g. Time Zones.
UPDATE:
For the sake of completeness and technically more correct.
The locale you are setting is invalid. For a complete list of available locales do this:
<cfdump var="#Server.coldfusion.supportedlocales#">
You will then see the correct locale should be:
<cfset SetLocale('indonesian (indonesia)') />
Related
I have an input text where I get the date:
<input type="text" name="myDate" />
After submitting the form, I save this date into the database doing a dateformat:
#DateFormat(myDate, "yyyy-mm-dd")#
If the user enters: 02/19/1948, it saves correct: 1948-02-19.
But if the user enters: 02191948, it saves: 7901-05-07. Why? Does anyone know how I can fix it?
Thanks
ColdFusion's DateFormat() expects a valid date representation. ColdFusion is very sloppy when it comes to what type of input is considered valid. Safe date inputs are ODBC literals and most of ISO 8601. Beware of format pitfalls like mm/dd and dd.mm and avoid them altogether, if possible.
What you want to use is LSParseDateTime(). It allows you to specify the locale and format you expect and make ColdFusion parse a date object based on the input. It's not fail-safe though, meaning you have to try-catch it in case the input doesn't match at all. There is a fail-safe LSIsDate(), which tells you if the input is considered valid in the specified locale. But either way, it's a game of format detection. Having fixed <select> tags for month, day and year is the easiest way to avoid issues.
Loose demo for localized date input:
<cfset myLocale = "en_US">
<cfset myDateFormat = "yyyy-mm-dd">
<cfset dateByInput = "">
<cfset errorReason = "">
<cfif structKeyExists(FORM, "myDate")>
<cfif lsIsDate(FORM["myDate"], myLocale)>
<cftry>
<cfset dateByInput = lsParseDateTime(FORM["myDate"], myLocale, myDateFormat)>
<cfcatch>
<cfset errorReason = ("Your input is invalid. Please enter in the following format: " & myDateFormat)>
</cfcatch>
</cftry>
<cfelse>
<cfset errorReason = ("Your input is invalid. Please enter in the following format: " & myDateFormat)>
</cfif>
</cfif>
<cfset dateByInputIsValid = isDate(dateByInput)> <!--- note: it's sufficient to use the unlocalized date check here, since dateByInput is either not valid at all or a (universal) date object --->
<cfif dateByInputIsValid>
<!--- store date input in database --->
<cftry>
<cfset myDatasource = "exampleDS">
<cfquery datasource="#myDatasource#">
INSERT INTO `myDatabase`.`myTable` ( `myDateColumn` ) VALUES (
<cfqueryparam value="#dateByInput#" cfSqlType="CF_SQL_TIMESTAMP">
)
</cfquery>
<cfcatch>
<cfset errorReason = "Oh noes, something went wrong attempting to save your input.">
</cfcatch>
</cftry>
</cfif>
<cfoutput>
<cfif dateByInputIsValid>
<p>Date input valid: #lsDateFormat(dateByInput, myDateFormat, myLocale)#</p>
<cfif len(errorReason)>
<p>#errorReason#</p>
<cfelse>
<p>Input successfully stored in database.</p>
</cfif>
<cfelse>
<cfif len(errorReason)>
<p>#errorReason#</p>
</cfif>
<form method="post">
<input type="text" name="myDate" />
<button type="submit">send</button>
</form>
</cfif>
</cfoutput>
I have following code:
<cfif session.language is ("DE")>
<cfset bl=ValueList(getContent.G,",")>
<cfelseif session.language is ("FR")>
<cfset bl=ValueList(getContent.H,",")>
<cfelseif session.language is ("EN")>
<cfset bl=ValueList(getContent.I,",")>
</cfif>
<cfset tags = sizes />
<cfset bltags = bl />
<cfset tagArray = arrayNew(1) />
<cfset tagArrayDATA = arrayNew(1) />
<cfloop list="#tags#" index="tag" delimiters=",">
<cfif not ArrayFindNoCase(tagArray,tag)>
<cfset arrayAppend(tagArray, tag) />
</cfif>
</cfloop>
<cfloop list="#bltags#" index="tag" delimiters=",">
<cfif not ArrayFindNoCase(tagArrayDATA,tag)>
<cfset arrayAppend(tagArrayDATA, tag) />
</cfif>
</cfloop>
<cfoutput>
<cfif isdefined("tagArray") AND arraylen(tagArray) GT 1>
<form name="frmsize" id="frmsize" action="/index.cfm?showusage" method="post">
<cfif isdefined("tagArray") AND arraylen(tagArray) GT 1>
<div>
<select name="valuesize">
<option value="">Choose your option</option>
<cfloop from="1" to="#arraylen(tagArray)#" index="i">
<option value="#tagArray[i]#">#tagArray[i]#
<cftry>
#tagArrayDATA[i]#
<cfcatch>
</cfcatch>
</cftry>
</option>
</cfloop>
</select>
</div>
</cfif>
</form>
</cfif>
</cfoutput>
My goal is to send a value from tagArrayDATA[i] via link.
It should look like that:
<form name="frmsize" id="frmsize" action="/index.cfm?showusage&valueArrayData="#tagArrayDATA[i]#" method="post">
I don't know how to manage that because the cfloop is below the action attribute of the form.
You can't really do what you are trying to do with server side code alone as far as I can tell. But you have a couple of options. One easy one is to just Javascript to update the action when the select is changed.
The other option is to put both values in the select and parse on the end.
<cfloop from="1" to="#arraylen(tagArray)#" index="i">
<option value="#tagArray[i]#-#tagArrayDATA[i]#">
#tagArray[i]# #tagArrayDATA[i]#
</option>
</cfloop>
Then when you are parsing the data just do:
<cfset data = listToArray(FORM.valuesize,'-') />
<!-- data[1] will be the selected value of #tagArray[i]# -->
<!-- data[2] will be the selected value of #tagArrayData[i]# -->
<!-- This assumes the - will never be actually in the data, you could use a different separator -->
My guess is they are both strings and this should work, though I have no idea why you have a try/catch in the select part of your code, probably look at a better way of doing that. If you really need that, I would clean it up as.
<cfloop from="1" to="#arraylen(tagArray)#" index="i">
<cfset data = '' />
<cftry>
<cfset data = tagArrayData[i] />
<cfcatch></cfcatch>
</cftry>
<option value="#tagArray[i]#-#data#">
#tagArray[i]# #data#
</option>
</cfloop>
Though if you are processing the data on the other end, I would make sure all the data is either in the FORM or the URL scopes but not mix. I would be pissed to have to parse some form data in the FORM scope and other data in the URL scope.
I was trying to implement 3 dependent drop downs in my code. But was unable to retrieve dates from my ColdFusion component. Here is the code in my .cfm template:
1st drop down
<cfselect name="city_code" class="styled-select"
bind="cfc:getcity.getcity1()"
bindonload="true" >
2nd drop down
<cfselect name="movie_id" class="styled-select"
bind="cfc:getcm.getmovies({city_code})">
</cfselect>
3rd drop down
<cfselect id="movie_id1" name="movie_id1"
class="styled-select"
bind="cfc:getcm.getdate({movie_id})"/>
In the 3rd drop down, I want to display dates for about five days from the current date. Here is my cfc code:
<cfset var data="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>
<cfquery name="data2" datasource="sqldb">
select movie_id,release_date
from shows
where movie_id = '#ARGUMENTS.movie_id#'
</cfquery>
<cfset result[1][1] = "0">
<cfset result[1][2] = " Select Date">
<cfloop index="i" from="1" to="#data2.recordcount#">
<cfset result[i+1][1]=data2.movie_id[i]>
<cfset result[i+1][2]=data2.release_date[i]>
</cfloop>
<cfreturn result>
This CFC is working for me, but I have to retrieve 5 dates before release date.
k try this way murali
<cfquery name="data2" datasource="bookonline">
select tid,daysb4booking
from shows
where movie_id = '#ARGUMENTS.movie_id#'
</cfquery>
<cfset arr=ArrayNew(1)>
<cfloop index="i" from="1" to="#data2.recordcount#">
<cfset arr[i]=data2.daysb4booking[i]>
</cfloop>
<cfset num=#LSNumberFormat(arraymax(arr))#>
<cfset result[1][1] = "0">
<cfset result[1][2] = " Select Date">
<!--- convert results to array--->
<cfloop index="i" from="1" to="#num#">
<cfset result[2][1]=data2.tid[1]>
<cfset result[2][2]=dateformat(dateadd("d",i,now()))>
</cfloop>
I am not sure if I am thinking about this correctly. I am still new to ColdFusion. I am creating a form which uses binding for the user to select a category and then a specific service. The code for the binding works great. The problem is that now I need to pull some additional information from the service to refer to another field. For example, if the service selected has a "Y" under additional info needed. A field will show that additional information is needed (this field is not changeable)
Originally I thought I could do something like regenerate the same query I did to pull the list of services and just refer to the service type that is selected. Yet I keep getting an error that the field is not defined. Here is the code that I am trying to make it work.
UPDATED: I got it to work I changed the code below the only problem is that I can not get the "Y" to display I get [object Object] instead. Any advice on how to display the text with use of cfinput?
CFC:
<!--- Get array of Catagory Description types --->
<cffunction name="cat_description" access="remote" returnType="array">
<!--- Define variables --->
<cfset var data="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>
<!--- Get data --->
<cfquery name="getServiceCat" datasource="Some Database">
select distinct 2 AS SortBy, CATG_NAME
from some table
UNION
select 1 AS SortBy, '' AS CATG_NAME
from Some table
order by SortBy
</cfquery>
<!--- Convert results to array--->
<cfloop index="i" from="1" to="#getServiceCat.recordcount#">
<cfset result[i][1]=getServiceCat.CATG_NAME[i]>
<cfset result[i][2]=getServiceCat.CATG_NAME[i]>
</cfloop>
<!--- And return it --->
<cfreturn result>
</cffunction>
<!--- Get Service Type by Cat description type --->
<cffunction name="getServiceType2" access="remote" returnType="array">
<cfargument name="CATG_NAME" type="string" required="true">
<cfset var data="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>
<cfquery name="getServiceType2" datasource="Some Database">
select 1 AS SortBy, '' AS SRTY_BNR, '' AS SRTY_NAME
from Some table
UNION
select distinct 2 AS SortBy, SRTY_NBR, SRTY_NAME
from Some Table
where CATG_NAME = <cfqueryparam value="#ARGUMENTS.CATG_NAME#"
cfsqltype="cf_sql_varchar">
order by SortBy
</cfquery>
<cfloop index="i" from="1" to="#getServiceType2.recordcount#">
<cfset result[i][1]=getServiceType2.SRTY_NAME[i]>
<cfset result[i][2]=getServiceType2.SRTY_NAME[i]>
</cfloop>
<cfreturn result>
</cffunction>
<!---Updated below table into CFC to pull information depending on what is pulled
from category and service type--->
<cffunction name="getLR" access="remote" returnType="query">
<cfargument name="SRTY_NAME" type="string" required="true">
<cfset var data="">
<!---Query to get "Y"--->
<cfquery name="lr_required" datasource="Some Datebase">
select distinct LAB_REL_NTFN_FLAG
from some table
where SRTY_NAME = <cfqueryparam value="#ARGUMENTS.SRTY_NAME#"
cfsqltype="cf_sql_varchar">
</cfquery>
<cfreturn lr_required>
</cffunction>
Here is the code within the form:
<TR id="serv_ty" style="display: inline;">
<td align="left" nowrap><label>Service Type:</label></td>
<td>Select Category:
<cfselect name="catdesc"
bind="cfc:servicetype2.cat_description()"
bindonload="true"/><br />
</td>
</TR>
<tr id="serv_ty2" style="display: inline;">
<td></td>
<td>Select Service:
<cfselect name="service_type"
bind="cfc:servicetype2.getServiceType2({catdesc})"
bindonload="false"/>
</td>
</tr>
This is the form code to use the bind which works but will not display the DATA:
<tr id="lr_verify" style="display: inline;">
<td></td>
<td>Additional Info Reuired:
<cfinput
name="lr_needed"
bind="cfc:servicetype2.getLR({service_type})"
bindonload="no"
disabled="disabled"
display="LAB_REL_NTFN_FLAG"/></td>
</tr>
Any advice on how to get it to display or if I should use a different CF statement with the bind to get the correct display. Thanks in advnace for your help on this.
Why am I missing the total on the checkout page?
Apologies.
As my code is working, because it actually got to PayPal and does have all the field correct.
I didn't think it was necessary to post the code.
I thought it could be answered simply, "you're missing the XXXX variable in your post to PayPal."
But, seeing as this is StackOverflow, code is required.
This is COLDFUSION (yes caps because people think this is a dead/dying language).
<cffunction name="expressCheckout" access="remote" returnformat="JSON" output="false" description="Processes PayPal Subscription">
<cfargument name="L_BILLINGAGREEMENTDESCRIPTION0" type="string" required="yes" />
<cfargument name="L_BILLINGTYPE0" type="string" required="yes" />
<cfargument name="AMT" type="numeric" required="yes" />
<cfset var username = "wpp_1306278086_biz_api1.blahblah.com">
<cfset var password = "1306278555">
<cfset var signature = "someSig">
<cfset var serverURL = "https://api-3t.sandbox.paypal.com/nvp">
<cfset var version = "65.1">
<cfset requestData = StructNew()>
<cfset requestData.USER = "#USERNAME#">
<cfset requestData.PWD = "#PASSWORD#">
<cfset requestData.SIGNATURE = "#SIGNATURE#">
<cfset requestData.SUBJECT = "">
<cfset requestData.VERSION = "#version#">
<cfset requestData.METHOD = "SetExpressCheckout">
<cfset requestData.AMT = "#arguments.AMT#">
<cfset requestData.DESC = "#arguments.L_BILLINGAGREEMENTDESCRIPTION0#">
<cfset requestData.CUSTOM = "#session.rfcid#">
<cfset requestData.returnURL = "http://localhost:8500/rfc2-1/membership/payPalConfirm.cfm">
<cfset requestData.cancelURL = "http://localhost:8500/rfc2-1/membership/creditcardform.cfm">
<cfset payPalReturn = doHttppost(requestData, serverURL, "no")>
<cfset payPalReturn = getNVPResponse(#URLDecode(payPalReturn)#)>
<cfif payPalReturn.ACK EQ "Failure">
<!--- return the error message --->
<cfset payPalReturn.ERRORMESSAGE = #payPalReturn.L_LONGMESSAGE0#>
</cfif>
<cfreturn payPalReturn>
</cffunction>
This retuns a json object to the browser.
The browser then sends me to:
https://sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=SomeToken
All fine when I get to PayPal. Just missing the total in the left hand box (as diagrammed)
Try appending &useraction=commit to the PayPal redirection URL (https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-xxxxxx&useraction=commit).
Not sure of this works for billing agreements, but worth a shot. It'll work for regular payments anyway.
edit:
Actually, on second thought; since it's a billing agreement, which is not for a fixed price (otherwise you wouldn't need a billing agreement in the first place); this would be intended. Since there is no specific price to display.