Datediff for datetime in different time zones - coldfusion

UPDATED
I need to get the hour and minute difference between two datetimes that are in different time zones.
I have the datetime in MySQL, and the offset from GMT, of the locations in MySQL.
What I have tried:
<cfset departure = CreateDateTime(2017,01,27,21,00,00)> <!--- (this time zone is +2) --->
<cfset arrival = CreateDateTime(2017,01,28,06,40,00)> <!--- (this time zone is -5) --->
<cfset depart_timezone = 2>
<cfset arrive_timezone = -5>
<cfset difference = datediff("h",departure,arrival)><!--- get the difference in hours --->
<cfset timezonedif = depart_timezone - arrive_timezone><!--- get the difference between the time zones (answer should be 7)--->
<cfset duration = difference + timezonedif><!--- add the time zone difference to the flight difference --->
<cfoutput>
(Duration: #duration# hours)<br>
</cfoutput>
This returns 16 hours which is not correct. The difference should be 15 hours and 40 minutes. Help will be appreciated. Been at this for hours.

You are doing things in the wrong order.
You need to get the correct date/times - so add / remove the timezone difference
<cfset departure = CreateDateTime(2017,01,27,21,00,00)> <!--- (this time zone is +2) --->
<cfset arrival = CreateDateTime(2017,01,28,06,40,00)> <!--- (this time zone is -5) --->
<cfset depart_timezone = -2>
<cfset arrive_timezone = 5>
<cfset tzDeparture = DateAdd('h',depart_timezone,departure)>
<cfset tzArrival = DateAdd('h',arrive_timezone,arrival)>
Then get the total amount of difference in minutes
<cfset difference = datediff("n",tzDeparture,tzArrival)>
Then just do the math to convert minutes to hours & minutes
<cfoutput>
Duration Total Mins: #difference#<br>
Duration Hours: #int(difference/60)#<br>
Duration Mins: #difference MOD 60#<br>
</cfoutput>
Output:
Duration Total Mins: 1000
Duration Hours: 16
Duration Mins: 40
You can see an example here: http://trycf.com/gist/26f5bce31db7787f4591317b7360ceb7/acf11?theme=monokai

Related

How can I get the Monday's date of the previous week and Friday's date of the previous week?

I am using ColdFusion 2016. What code is needed to get the previous Monday in the previous week and the previous Friday in the previous week?
This code below gets the previous Monday, but I want the previous Monday in the previous week. Same thing for Friday.
<cfset currentDate = Now() />
<cfset mostRecentMonday = dayOfWeek(currentDate) gt 1 ? dateAdd("d", 2-
dayOfWeek(currentDate), currentDate) : dateAdd("d", -6, currentDate) />
You just need to simplify your solution.
<cfset currentDate = Now() />
<cfset obj = {}>
<cfset todaydayOfWeek = dayOfWeek(currentDate)>
<cfset mondayOffset = (2-todaydayOfWeek)-7>
<cfset fridayOffset = (6-todaydayOfWeek)-7>
<cfset obj.mostRecentMonday = dateAdd("d", mondayOffset, currentDate)>
<cfset obj.mostRecentFriday = dateAdd("d", fridayOffset, currentDate)>
<cfdump var="#obj#">
DEMO
You can get last Friday like,
<cfset today=dayofweek(now())>
<span>Last Friday is:</span>
<cfif today eq 7>
<span>#dateformat(dateAdd("d",-1,now()))#</span>
<cfelse>
<span>#dateformat(dateAdd ("d",-(1+today),now()))#</span>
</cfif>
Last Monday :
<cfif today eq 7>
<span>#dateformat(dateAdd("d",-5,now()))#</span>
<cfelse>
<span>#dateformat(dateAdd ("d",-(5+today),now()))#</span><br>
</cfif>
#user1669296, make sure, your last Monday also return wrong value.For ex. Today ( 06-sep-2018) is Monday if you run that code it's will return today date only not last Monday. So please correct it too.

Coldfusion convert from UNIX to human readable time without converting the time between the time zones

i need a conversion from UNIX to human readable time but i don't want to convert the time between the time zones like the following code does:
<cffunction name="EpochToDate" hint="Returns Epoch from Date">
<cfargument name="dateSeconds" default="">
<cfscript>
// set the base time from when epoch time starts
startDate = createdatetime( '1970','01','01','00','00','00' );
if ( NOT isnumeric( arguments.dateSeconds ) )
return '';
// return the date
// this adds the seconds to the startDate and the converts it to to a local time from UTC format
return dateConvert( "utc2Local", dateadd( 's', arguments.dateSeconds, startDate ) );
</cfscript>
</cffunction>
For example the timestamp 1532118000 should return the GMT: Friday, 20 July 2018 8:20:00 PM and not server's time zone date.
I think the approach you need here is to convert the epoch time from UTC to local first and then do the operation on it. Once that is done you can convert it back to UTC time. I tried this on two servers one is in a forward timezone from UTC and another which is behind.
<cffunction name="EpochToDate" hint="Returns Epoch from Date" output="true">
<cfargument name="dateSeconds" default="">
<cfscript>
// set the base time from when epoch time starts
startDate = DateConvert("utc2Local", CreateDateTime( 1970,1,1,0,0,0 ));
writedump(startDate);
if ( NOT isnumeric( arguments.dateSeconds ) )
return '';
// return the date
// this adds the seconds to the startDate and the converts it to to a local time from UTC format
return DateConvert("local2Utc", dateadd( 's', arguments.dateSeconds, startDate ));
</cfscript>
</cffunction>
<cfdump var="#EpochToDate(1532118000)#">
DEMO
UTC +5:30 {ts '1970-01-01 05:30:00'} {ts '2018-07-20 20:20:00'}
UTC -7:00 {ts '1969-12-31 17:00:00'} {ts '2018-07-20 20:20:00'}

Using cfqueryparam with constants

We religiously use cfqueryparam in our SQL queries.
Some of my predecessors seem to have been a little overzealous when using it with direct values rather than variables.
Isn't
record_is_deleted_bt = <cfqueryparam cfsqltype="cf_sql_bit" value="0">
overkill? I mean, there's no chance for SQL injection and I don't think that using a bind variable here does anything helpful vis-à-vis improving performance in the database. Wouldn't it be just as reasonable to do
record_is_deleted_bt = 0
?
Is there any advantage to using cfqueryparam in such an instance, besides ingraining the habit of using it? Is there a disadvantage?
No, this is not overkill. cfqueryparam's first job is data binding. It helps in sql injection prevention is just the add-on bonus. The prepared statements through data binding execute faster. You are wrong to assume that it is there to help on sql attack prevention only.
Important Note:
I am adding Test case provided by #Dan Bracuk on an oracle db.
<cfquery name="without" datasource="burns">
select count(*)
from burns_patient
where patientid = 1
</cfquery>
<cfquery name="with" datasource="burns">
select count(*)
from burns_patient
where patientid = <cfqueryparam cfsqltype="cf_sql_integer" value="1">
</cfquery>
<cfscript>
TotalWithout = 0;
TotalWith = 0;
</cfscript>
<cfloop from="1" to="1000" index="i" step="1">
<cfquery name="without" datasource="burns" result="resultwithout">
select count(*)
from burns_patient
where patientid = 1
</cfquery>
<cfquery name="with" datasource="burns" result="resultwith">
select count(*)
from burns_patient
where patientid = <cfqueryparam cfsqltype="cf_sql_integer" value="1">
</cfquery>
<cfscript>
TotalWithout += resultwithout.executiontime;
TotalWith += resultwith.executiontime;
</cfscript>
</cfloop>
<cfdump var="With total is #TotalWith# and without total is #TotalWithout#.">
The with total ranges from 700 to 900 total milliseconds. The without total ranges from 1800 to 4500 milliseconds. The without total is always at least double the with total.

Coldfusion CreateDate Issue

I'm having some trouble with the CreateDate() function, it's just erroring and I have no idea why!
I am running this query to get all of the dates from news stories so that I can create a news archive monthly.
<cfquery name="selectNews" datasource="#Request.dsn#">
SELECT Month(NewsDate) AS theCount
FROM news
GROUP BY Month(NewsDate)
</cfquery>
Then when I output it, I'm trying to output it in the following format
Aug 2012
Sept 2012
Oct 2012
So I'm using the following code to try to output this list
<ul>
<cfloop query="selectNews">
<cfoutput>
<cfset theDay = DateFormat(Now(), 'dd')>
<cfset theMon = theCount>
<cfset theYear = DateFormat(Now(), 'yyyy')>
<li>#CreateDate(theYear, theMon, theDay)#</li>
</cfoutput>
</cfloop>
</ul>
It works fine for the first item, it will output Aug 2012, however it will then error, saying this
Error Occurred While Processing Request
MONTH
Which to me, at least, is useless!
My guess is that the SQL Month() function is returning a 0 for January and CreateDate expects a 1 for January.
Edit
<ul>
<cfloop query="selectNews">
<cfset theDay = Day(Now())>
<cfset theMon = #theCount#>
<cfset theYear = Year(Now())>
<cfoutput><li>#DateFormat(CreateDate(theYear, theMon, theDay), "mmm yyyy")#</li></cfoutput>
</cfloop>
</ul>
Edit
This seems to be working but only with odd numbered months
<cfset months = [1,3,5] />
<ul>
<cfloop array="#months#" index="currentmonth">
<cfoutput><li>#DateFormat(CreateDate(Year(Now()), currentmonth, Day(Now())), "mmm yyyy")#</li></cfoutput>
</cfloop>
</ul>
This was me being an idiot. I was using DateFormat(Now(), 'dd'), which is a huge stupid mistake, seeing as there is only 30 days in September. It was running CreateDate(2012, 09, 31), which obviously won't work!

What is the quickest way in ColdFusion to get first and last day of quarter?

What is the quickest way in ColdFusion to get first and last day of quarter?
There doesn't seem to be a built in function for this.
First day of quarter:
FirstDayOfQuarter = CreateDate(year, (quarter-1)*3 + 1, 1)
Last day of quarter:
LastDayOfQuarter = DateAdd("d", -1, DateAdd("m", 3, FirstDayOfQuarter))
I have a feeling that your question might be more complex that it appears... for most purposes these values are a known set - no need to calculate:
Quarters:
January 1 - March 31
April 1 - June 30
July 1 - September 30
October 1 - December 31
Since the set is known in advance there's no real need for a function for this - determine in which date a quarter falls is a simple series of "if" statements (psuedocode):
if date > Oct 1 then Q4 else
if date > Jul 1 then Q3 else
if date > Apr 1 then Q2 else
if date > Jan 1 then Q1
(You do the check backwards in this case to check for the most restrictive match first. Although, as Kimvais points out, there is a function to do exactly that already in CFML.)
It should be essentilly the same for other "quarter" systems unless those dates are calculated in some way.
If I've missed the mark feel free to add comment to clarify.
The problem is that "quarter" is a relative term, while many organizations follow the default quarter breakdown of a year starting Jan 1 through Dec 31, many other organizations follow other quarters.
For example most retail organizations. Particularly those that depend on Christmas, don't want to be spending time doing end of quarter/year financials in december. They also want the entire holiday season (including the 2 weeks afterwards) on the same books as the rest of the season. So for them the "year" begins Feb 1.
The U.S. federal government and most of the states begin their financial year Oct 1 because of the way the legislature, elections and budgets work.
So a single function that always worked off of just one quarter layout would never work. Any of the functions listed in the other answers are fine I'm sure as long as your program is only dealing with one set. But if your coding a general use application then you may want to make it configurable.
Looks like there is a function for finding out the Quarter, based on this you could hardcode these?
I don't think there are built in functions for this - it's not clear whether you're looking for the numeric day of month or the string day of month (e.g. Monday). Anyway, this may be a little over-the-top - two functions which require an integer quarter value, and return the first and last dates of the quarter for further manipulation:
<cffunction name="QuarterFirstDate" returnType="date">
<cfargument name="quarternumber" required="yes" type="numeric">
<cfargument name="yr" type="numeric" default="2009">
<cfargument name="startmonth" type="numeric" default="1">
<cfset firstDate = DateAdd("m",startmonth-1,CreateDate(yr, ((quarternumber-1)*3)+1, "1"))>
<cfreturn firstDate>
</cffunction>
<cffunction name="QuarterLastDate" returnType="date">
<cfargument name="quarternumber" required="yes" type="numeric">
<cfargument name="yr" type="numeric" default="2009">
<cfargument name="startmonth" type="numeric" default="1">
<cfset lastDate = DateAdd("m",startmonth-1,CreateDate(yr, quarternumber*3, DaysInMonth(CreateDate(yr, quarternumber*3, "1"))))>
<cfreturn lastDate>
</cffunction>
<cfset year = "2009">
<cfset startmonth = "1">
<cfloop index="quarter" from="1" to="4">
<cfoutput>
<h2>Quarter #quarter#</h2>
#DateFormat(QuarterFirstDate(quarter, year, startmonth))#, day #DayOfYear(QuarterFirstDate(quarter, year, startmonth))#, #DayOfWeekAsString(DayOfWeek(QuarterFirstDate(quarter, year, startmonth)))#<br />
#DateFormat(QuarterLastDate(quarter, year, startmonth))#, day #DayOfYear(QuarterLastDate(quarter, year, startmonth))#, #DayOfWeekAsString(DayOfWeek(QuarterLastDate(quarter, year, startmonth)))#<br />
</cfoutput>
</cfloop>
edit: updated to allow a quarter start month to be specified
How about?
<cfset dt = now()>
<cfset DateLastQuarter = DateAdd("m",-3,dt)> <!--- Any date three months ago falls in previous quarter --->
<cfset quarterNumber = (month(DateLastQuarter)-1)\3+1> <!--- range from quarter 1-4 --->
<cfset StartQuarterMonth = (quarterNumber-1)*3+1> <!--- start of quarter month-number where Jan=1 (Mathematical magic) --->
<cfset LastQuarterFrom = CreateDate(year(DateLastQuarter),StartQuarterMonth,1)>
<cfset LastQuarterTo = DateAdd("d",-1,DateAdd("m",3,LastQuarterFrom))> <!--- the day before three months later --->
this above returns the first date in the previous quarter in LastQuarterFrom
and the last date in the previous quarter in LastQuarterTo