• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 115
  • Last Modified:

I am trying to set a time variable based on the current time with ColdFusion

I am trying to use the below code to change a variable based on the current time. The left column would be a current time range, the right column is what I want to set the variable to. I'm not sure how to handle the overlapping of days.  Could someone assist?

23:01 to 07:00  same day(or next day if past 12) 15:30
07:01 to 15:30  same day 23:00
15:31 to 23:00      next day 15:30

<cfset currentDateTime=Now()> 
<cfset theDateTimeand1 = #DateAdd("h",1,currentDateTime)# />
<cfif hour(theDateTimeand1) gte 23 and hour(theDateTimeand1) lte 7 >
      <cfset variables.CompleteBy = dateFormat(dateAdd("d", 1, theDateTimeand1), "yyyy/mm/dd")&" 15:30:00">
<cfelseif hour(theDateTimeand1) gte 7 and hour(theDateTimeand1) lte 15:30 >
      <cfset variables.CompleteBy = dateFormat(theDateTimeand1, "yyyy/mm/dd")&" 23:00:00">
<cfelseif hour(theDateTimeand1) gt 15:30 and hour(theDateTimeand1) lte  23>
      <cfset variables.CompleteBy = dateFormat(dateAdd("d", 1, theDateTimeand1), "yyyy/mm/dd")&" 15:30:00>
</cfif>

Open in new window

0
earwig75
Asked:
earwig75
  • 3
  • 3
1 Solution
 
Justin SmithWriterCommented:
Does this help or is it irrelevant?

http://c2.com/cgi/wiki?TestIfDateRangesOverlap

and try reading this page and the first comment is the answer:

http://stackoverflow.com/questions/2231406/using-coldfusion-how-do-i-determine-if-a-given-time-span-occurs-during-business

basically you just have to set a range using a formula...kinda like this, but read those pages it will make sense.

(StartA <= EndB) and (EndA >= StartB)

Proof:
Let ConditionA Mean that DateRange A Completely After DateRange B
_                        |---- DateRange A ------|
|---Date Range B -----|                           _
(True if StartA > EndB)

Let ConditionB Mean that DateRange A is Completely Before DateRange B
|---- DateRange A -----|                       _
 _                          |---Date Range B ----|
(True if EndA < StartB)

Then Overlap exists if Neither A Nor B is true -
(If one range is neither completely after the other,
nor completely before the other, then they must overlap.)

Now one of De Morgan's laws says that:

Not (A Or B) <=>  Not A And Not B

Which translates to: (StartA <= EndB)  and  (EndA >= StartB)

NOTE: This includes conditions where the edges overlap exactly. If you wish to exclude that,
change the >= operators to >, and <= to <

NOTE2. Thanks to @Baodad, see this blog, the actual overlap is least of:
{ endA-startA, endA - startB, endB-startA, endB - startB }
0
 
_agx_Commented:
EDIT: Fix code typo

Justin's logic is a solid way to check a date and/or time against a range. Though in this scenario, most of it could be handled by a single >= or <= comparison. Ultimately you can reduce it to 3 checks:

- If current time is between midnight and 7 AM -> use current day 15:30
- If current time is between 7:01 and 15:30 -> use same day 23:00
- Otherwise, the time must be between 15:31 and 23:59 -> use next day 15:30

Function:
<cfscript>
	// ** Requires CF10+ **
	public date function calculateCompleteByDate( date currentDateTime ) {

		Local.currentTime 	 = createTime( hour(arguments.currentDateTime), minute(arguments.currentDateTime), 0 );
		Local.todaysDate  	 = dateFormat( arguments.currentDateTime, "yyyy-mm-dd");
		Local.tomorrowsDate  = dateFormat( dateAdd("d", 1, arguments.currentDateTime), "yyyy-mm-dd");
		
		// Between midnight and 7:00 AM -> due same day at 15:30
		if (local.currentTime <= createTime(7,0,0)) {
			Local.completeBy = Local.todaysDate &" 15:30:00" ;
		}
		// Between 7:01 and 15:30 -> due same day at 23:00
		else if (local.currentTime >= createTime(7,1,0) && local.currentTime <= createTime(15,30,0)) {
			Local.completeBy = Local.todaysDate &" 23:00:00" ;
		}
		// Otherwise it is between 15:31 and 23:59:59 -> due tomorrow at 15:30 
		else {
			Local.completeBy = Local.tomorrowsDate &" 15:30:00";
		}

		// *** DEMO ONLY ****
		writeOutput("<br>[#dateTimeFormat(arguments.currentDateTime, 'yyyy-MM-dd HH:nn:ss tt')#] 
					 --> #dateTimeFormat(Local.completeBy, 'yyyy-MM-dd HH:nn:ss tt')# "
				);
		
		return parseDateTime(Local.completeBy, "yyyy-MM-dd HH:mm:ss");
	}
</cfscript>

Open in new window


Usage:
<cfscript>
	dates = [ 
				createDateTime( 2016,8,4, 0, 0, 0)
				, createDateTime( 2016,8,4, 7, 0, 0)
				, createDateTime( 2016,8,4, 7, 1, 0)
				, createDateTime( 2016,8,4, 15, 30, 0)
				, createDateTime( 2016,8,4, 15, 31, 0)
				, createDateTime( 2016,8,4, 23, 0, 0)
				, createDateTime( 2016,8,4, 23, 1, 0)
				, createDateTime( 2016,8,4, 23, 59, 0)
			];
	for (value in dates) {
		calculateCompleteByDate( value );
	}
</cfscript>

Open in new window

0
 
earwig75Author Commented:
@AGX, thank you. I now understand the function/script, but how can I use it? I am just trying to have the completeByDate output to a page, depending on the current time. I think I'm going to be using it as the default value in a text box/date picker. Would you be able to help with that?
0
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
_agx_Commented:
@earwig75 - There are different options. Simplest is to include the function definition somewhere in your .cfm page.  

<cfscript>
	public date function calculateCompleteByDate( date currentDateTime ) {
              // .... function content here 
	     return parseDateTime(Local.completeBy, "yyyy-MM-dd HH:mm:ss");
	}
</cfscript>

Open in new window


Then invoke it where ever you need it and output the value as usual:

         
<cfoutput>Complete By Date: #calculateCompleteByDate( now() )#</cfoutput>

Open in new window


IMO wrapping the logic in a function is cleaner, but it is not required. You could just as easily do it all inline if you prefer:

<cfscript>
	variables.currentDateTime = now();
	variables.currentTime 	 = createTime( hour(variables.currentDateTime), minute(variables.currentDateTime), 0 );
		
	// Between midnight and 7:00 AM -> due same day at 15:30
	if (variables.currentTime <= createTime(7,0,0)) {
		variables.completeBy = dateFormat( variables.currentDateTime, "yyyy-mm-dd") &" 15:30:00" ;
	}
	// Between 7:01 and 15:30 -> due same day at 23:00
	else if (variables.currentTime >= createTime(7,1,0) && variables.currentTime <= createTime(15,30,0)) {
		variables.completeBy = dateFormat( variables.currentDateTime, "yyyy-mm-dd") &" 23:00:00" ;
	}
	// Otherwise it is between 15:31 and 23:59:59 -> due tomorrow at 15:30 
	else {
		variables.completeBy = dateFormat( dateAdd("d", 1, variables.currentDateTime), "yyyy-mm-dd") &" 15:30:00";
	}

        // Display complete by date
	writeOutput("Complete by: "& parseDateTime(variables.completeBy, "yyyy-MM-dd HH:mm:ss"));
	
</cfscript>

Open in new window

0
 
earwig75Author Commented:
As you have probably guessed, I am not that great with CFSCRIPT, that's why I was using cfif statements in my example.  I have one last question if you don't mind. In your function, there are 2 variables (I underlined them below). Can you explain why there is a "date" and a "currentDateTime"?  I am only passing one variable to the function. Sorry for being so confused!

public date function calculateCompleteByDate( date currentDateTime ) {
0
 
_agx_Commented:
public date function calculateCompleteByDate( date currentDateTime ) {

No problem.  It's actually one variable "name" and the variable's data type. If you break it down, it's just like cffunction:

public                                     --->      CFFunction "access" level:     "public", "private", etc....
date                                        --->      CFFunction "returntype":     "date", "string", etc....
function                                 --->      Keyword identifying code block as UDF, ie "cffunction"
calculateCompleteByDate  --->   CFFunction "name"
(
          date                              --->  CFArgument "type", ie "date", "string", etc....
          currentDateTime        --->  CFArgument "name"
)

Here's the same signature in cfml:


<cffunction name="calculateCompleteByDate" returntype="date" access="public">
	        <cfargument name="currentDateTime" type="date">
                ....

Open in new window




CFML Version:

<cffunction name="calculateCompleteByDate" returntype="date" access="public">
	<cfargument name="currentDateTime" type="date">
	
	<cfset Local.currentTime 	 = createTime( hour(arguments.currentDateTime), minute(arguments.currentDateTime), 0 )>
	<cfset Local.todaysDate  	 = dateFormat( arguments.currentDateTime, "yyyy-mm-dd")>
	<cfset Local.tomorrowsDate  = dateFormat( dateAdd("d", 1, arguments.currentDateTime), "yyyy-mm-dd")>
		
	<!--- Between midnight and 7:00 AM -> due same day at 15:30 --->
	<cfif (local.currentTime lte createTime(7,0,0))>
		<cfset Local.completeBy = Local.todaysDate &" 15:30:00" >
	<!--- Between 7:01 and 15:30 -> due same day at 23:00 --->
	<cfelseif (local.currentTime gte createTime(7,1,0) && local.currentTime lte createTime(15,30,0))>
		<cfset Local.completeBy = Local.todaysDate &" 23:00:00" >
	<!--- Otherwise it is between 15:31 and 23:59:59 -> due tomorrow at 15:30 --->
	<cfelse>
		<cfset Local.completeBy = Local.tomorrowsDate &" 15:30:00">
	</cfif>
	
	<!--- DEBUG / DEMO ONLY ---->
	<cfoutput>
		<br>[#dateTimeFormat(arguments.currentDateTime, 'yyyy-MM-dd HH:nn:ss tt')#] 
		--> #dateTimeFormat(Local.completeBy, 'yyyy-MM-dd HH:nn:ss tt')# 
	</cfoutput>
	
	<cfreturn parseDateTime(Local.completeBy, "yyyy-MM-dd HH:mm:ss")>
</cffunction>

Open in new window

0
 
earwig75Author Commented:
You're the best, thank you!
0

Featured Post

Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

  • 3
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now