Page 1 of 1

Detecting various intervals of time

Posted: Thu Jul 19, 2007 4:17 pm
by Kaiser
Hey guys!

I've been working on a program we need at work and there needs to happen something specific between intervals of time... mm... let me explain myself better: Let's say I have a file with some intervals...

Morning: 6:50 - 8:30
Mid-Day: 12:15 - 14:30
Afternoon: 17:10 - 19:50

How would I do some conditionals for detecting those intervals? I've been trying to get it right for weeks with no avail :(... any help would be greatly appreciated!!! :D

Posted: Thu Jul 19, 2007 4:34 pm
by Xombie
Windows only, or...? Would it bother you to use an API solution?

Posted: Thu Jul 19, 2007 4:37 pm
by Kaeru Gaman
best choice would be converting the intervals into numeric values first, I think.

Posted: Thu Jul 19, 2007 4:54 pm
by Kaiser
Xombie wrote:Windows only, or...? Would it bother you to use an API solution?
Windows-only, yes. And no, it wouldn't bother me :).
Kaeru Gaman wrote:best choice would be converting the intervals into numeric values first, I think.
I have done that already :P, there's a variable which holds the hour and another one which holds the minute.

Posted: Thu Jul 19, 2007 5:02 pm
by Kaeru Gaman
there's a variable which holds the hour and another one which holds the minute.
I meant to use one variable to hold the complete time,
this will make a simple comparison with ">" and "<" possible...

I coded a little example rightaway...

I introduced a Time-format that holds the second of the day,
different to the Linux-timestamp that holds the second since Jan.1.1970

Code: Select all

EnableExplicit

Define.l Morning1, Morning2, MidDay1, MidDay2, Afternoon1, Afternoon2, TestTime, ActTime

Procedure.s Time_NumToString( Time.l )
  Protected Sec.l, Min.l, Hor.l, Time$
  Sec = Time % 60
  Time / 60
  Min = Time % 60
  Time / 60
  Hor = Time % 24
  Time$ = RSet(Str(Hor),2,"0")+":"+RSet(Str(Min),2,"0")+":"+RSet(Str(Sec),2,"0")
  ProcedureReturn Time$
EndProcedure

Procedure.l Time_StringToNum( Time$ )
  Protected Sec.l, Min.l, Hor.l, Time.l
  Sec = ( Val( Mid( Time$, 7, 2 ) ) ) % 60
  Min = ( Val( Mid( Time$, 4, 2 ) ) ) % 60
  Hor = ( Val( Mid( Time$, 1, 2 ) ) ) % 60
  Time = 3600 * Hor + 60 * Min + Sec
  ProcedureReturn Time
EndProcedure

Procedure.l Time_GetActual()
  Protected Sec.l, Min.l, Hor.l, Time.l
  Time = Date()
  Sec = Second(Time)
  Min = Minute(Time)
  Hor = Hour(Time)
  Time = 3600 * Hor + 60 * Min + Sec
  ProcedureReturn Time
EndProcedure

TestTime = Time_StringToNum( "13:27:15" )
ActTime = Time_GetActual()

Debug "Time to test is " + Time_NumToString( TestTime )
Debug "Actual time is " + Time_NumToString( ActTime )

Debug "---------------------------------"


Morning1 = Time_StringToNum( "06:50:00" )
Debug "Morning starts at " + Time_NumToString( Morning1 )
Morning2 = Time_StringToNum( "08:30:00" )
Debug "Morning ends at " + Time_NumToString( Morning2 )

MidDay1 = Time_StringToNum( "12:15:00" )
Debug "MidDay starts at " + Time_NumToString( MidDay1 )
MidDay2 = Time_StringToNum( "14:30:00" )
Debug "MidDay ends at " + Time_NumToString( MidDay2 )

Afternoon1 = Time_StringToNum( "17:10:00" )
Debug "Afternoon starts at " + Time_NumToString( Afternoon1 )
Afternoon2 = Time_StringToNum( "19:50:00" )
Debug "Afternoon ends at " + Time_NumToString( Afternoon2 )

Debug "---------------------------------"

If TestTime > Morning1 And TestTime < Morning2
  Debug "TestTime is in the Morning"
ElseIf TestTime > MidDay1 And TestTime < MidDay2
  Debug "TestTime is in the MidDay"
ElseIf TestTime > Afternoon1 And TestTime < Afternoon2
  Debug "TestTime is in the Afternoon"
ElseIf TestTime > Morning2 And TestTime < MidDay1
  Debug "TestTime is between Morning and MidDay"
ElseIf TestTime > MidDay2 And TestTime < Afternoon1
  Debug "TestTime is between MidDay and Afternoon"
Else
  Debug "TestTime is in the Night"
EndIf

If ActTime > Morning1 And ActTime < Morning2
  Debug "ActTime is in the Morning"
ElseIf ActTime > MidDay1 And ActTime < MidDay2
  Debug "ActTime is in the MidDay"
ElseIf ActTime > Afternoon1 And ActTime < Afternoon2
  Debug "ActTime is in the Afternoon"
ElseIf ActTime > Morning2 And TestTime < MidDay1
  Debug "ActTime is between Morning and MidDay"
ElseIf ActTime > MidDay2 And TestTime < Afternoon1
  Debug "ActTime is between MidDay and Afternoon"
Else
  Debug "ActTime is in the Night"
EndIf
sure you should put tests in procedures, but I was to lazy to add this for the example...

Posted: Thu Jul 19, 2007 5:47 pm
by Xombie
A quick and dirty way to do it with the API...

Code: Select all

;-
EnableExplicit
;-
Global gPause.l
Global gHandleTimer.l
;-
Procedure Greet(Which.s)
   ;
   MessageRequester("Hi!", Which)
   ;
EndProcedure
;-
Procedure.l CallbackTimer(Handle.l, uMsg.l, idEvent.l, dwTime.l)
   ;
   Protected HoldTime.l
   ;
   If gPause = #False
      ; Do not run the callback if the user paused it.  There are a lot of ways to block this.  Another way
      ; would be to use a global variable to store dwTime above and check against that.
      gPause = #True
      ; Pause the callback procedure so it doesn't run again until after the local stuff is processed.
      HoldTime = Date()
      ;
      If Hour(HoldTime) >= 6 And Hour(HoldTime) <= 8
         ;
         If (Hour(HoldTime) = 6 And Minute(HoldTime) >= 50) Or Hour(HoldTime) = 7 Or (Hour(HoldTime) = 8 And Minute(HoldTime) <= 30)
            ;
            Greet("Morning!")
            ;
         EndIf
         ;
      ElseIf Hour(HoldTime) >= 17 And Hour(HoldTime) <= 19
         ;
         If (Hour(HoldTime) = 17 And Minute(HoldTime) >= 10) Or Hour(HoldTime) = 18 Or (Hour(HoldTime) = 19 And Minute(HoldTime) <= 50)
            ;
            Greet("Afternoon!")
            ;
         EndIf
         ;
      ElseIf Hour(HoldTime) >= 12 And Hour(HoldTime) <= 14
         ;
         If (Hour(HoldTime) = 12 And Minute(HoldTime) >= 15) Or Hour(HoldTime) = 13 Or (Hour(HoldTime) = 14 And Minute(HoldTime) <= 30)
            ;
            Greet("Mid-Day!")
            ;
         EndIf
         ;
      EndIf
      ;
      gPause = #False
      ; Unpause the callback.
   EndIf
   ;
EndProcedure
;-
gHandleTimer = SetTimer_(#Null, #Null, 5000, @CallbackTimer())
; The time will be checked every 10 second.
;-
If OpenWindow(0, 0, 0, 200, 200, "Test", #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_TitleBar)
   ;
   If CreateGadgetList(WindowID(0))
      ;
      ;
   EndIf
   ;
EndIf
;-
While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend
;-
KillTimer_(#Null, gHandleTimer)
;-

Posted: Fri Jul 20, 2007 2:42 am
by Techie42
Here's my attempt at a general routine...I hope it helps you get where you want to be :D (P.S. PB 4.02)

Code: Select all

; -------------------------------------------------------------------------------------------------------
;
;	PURPOSE:
;		Date / time interval checking routines.
;
;
;	CREATED:
;		Techie42, 20th July 2007.
;
;
;	NOTES:
;		(i) 	This only works for dates AFTER 1st January 1970 (up to 2034),
;				due to the way in which the "Date()" function works.
;		(ii)	This will only work for time intervals that span the same day
;				(i.e. it will not work for intervals starting before midnight and ending after midnight)
;
;	LICENSE:
;		Do with this as you wish, in any manner, either privately or commercially.
;		This is for general public consumption without any limitations.
;		The original author will not, and cannot, be held responsible for any issues arising
;		out of the use of this code.
;
;
;	USAGE:
;		(i)		Define the linked list which contains the time ranges, as many as required, without overlapping ranges
;		(ii)	Define a variable to contain the return values, if any
;		(iii)	Call "checkInterval" to test a given time against the ranges
;		(iv)	If successful, populate the variable from step (ii) with the relevant values
;		(v)		Return True if a range is found, else return False
;
; -------------------------------------------------------------------------------------------------------

; Always ensure variables are explicitly declared
EnableExplicit


; Define the structure we will use to hold time ranges
Structure		timeInterval
	intervalTag.s				; The name of the range		i.e. "Mid-Day"
	intervalBegin.s				; The range starting time	i.e. "12:15"
	intervalEnd.s				; The range ending time		i.e "14:30"
EndStructure


;
; PROCEDURE:
;		checkInterval
;
; This routine checks the time ranges defined in the linked list to see if there is a match
; with a given time
;
; PARAMETERS:
;	checkInterval( linkedList <required>, *returnItem <required>, timeToCheck <optional> )
;
;	linkedList			This should be of the type "timeInterval", and is populated with the
;						time ranges you wish to check
;
;	*returnItem			This pointer to a variable of type "timeInterval" is used to supply
;						the return values, if relevant  i.e. a match is found
;
;	timeToCheck			If present, this is a time in the format "hh:mm"
;						If not supplied, then the current computer time is used
;
Procedure.l	checkInterval(intervalList.timeInterval(), *returnItem.timeInterval, timeCheck.s = "NOW")
	Protected		returnState.l			; The value returned from this procedure
	
	Protected		currentTimeIndex.l		; The time to check, either supplied or computer time
	Protected		intervalBegin.l			; Will hold the range starting time
	Protected		intervalEnd.l			; Will hold the range ending time
	
	Protected		saveIndex.l				; Let's be helpful and save the list index for the linked list
											; so that we can restore the linked list index to the same position
											; once we have finished walking the list
	
	Protected		bDone.l					; Boolean flag for indicating the end of a loop
	

	; Ensure we have something in the linked list and something as the time to test...
	If (intervalList() And (Len(Trim(timeCheck)) > 0))
		; Make sure there are some items in the linked list...
		If (CountList(intervalList()) > 0)
			; If the time to test is not supplied, then the default value of "NOW" is used, so we
			; will use the current computer time...otherwise we break the supplied time into
			; hours and minutes...and convert this into the number of seconds since 1st January 1970...
			If (timeCheck = "NOW")
				currentTimeIndex	= Date()
			Else
				currentTimeIndex	= Date(Year(Date()), Month(Date()), Day(Date()), Val(StringField(timeCheck, 1, ":")), Val(StringField(timeCheck, 2, ":")), 0)
			EndIf
			
			; Ensure the time (supplied or otherwise) is actually valid...
			If (currentTimeIndex <> -1)
				bDone		= #False
				
				; Remember the current list index for restoration later on...
				saveIndex	= ListIndex(intervalList())
				
				; We want to walk the linked list, so start at the beginning...
				ResetList(intervalList())
				
				; Process all linked list items until we either run out, or we have found a match...
				While (NextElement(intervalList()) And (Not bDone))
					; Get the range starting and ending times in the correct format...
					; ...the number of seconds since 1st January 1970...
					intervalBegin	= Date(Year(Date()), Month(Date()), Day(Date()), Val(StringField(intervalList()\intervalBegin, 1, ":")), Val(StringField(intervalList()\intervalBegin, 2, ":")), 0)
					intervalEnd		= Date(Year(Date()), Month(Date()), Day(Date()), Val(StringField(intervalList()\intervalEnd, 1, ":")), Val(StringField(intervalList()\intervalEnd, 2, ":")), 0)
					
					; Test to see if the currently selected range encompasses the required time check...
					If ((intervalBegin <= currentTimeIndex) And (currentTimeIndex <= intervalEnd))
						; If so, then let's return something useful, and indicate the process was successful...
						*returnItem\intervalTag		= intervalList()\intervalTag
						*returnItem\intervalBegin	= intervalList()\intervalBegin
						*returnItem\intervalEnd		= intervalList()\intervalEnd

						bDone	= #True
					EndIf
				Wend
				
				; Be tidy and leave the linked list as we found it...
				SelectElement(intervalList(), saveIndex)
				
				; If we found a match, return True, else return False...
				returnState	= bDone
			Else
				; If there is no match, or something is invalid, we return False...
				returnState	= #False
			EndIf
		Else
			; There were no items in the linked list...
			returnState	= #False
		EndIf
	Else
		; One or more of the parameters were invalid...probably...
		returnState	= #False
	EndIf
	
	; Return the state...
	ProcedureReturn returnState

EndProcedure


; This procedure is just to show how one procedure can call checkInterval, passing the relevant parameters.
; This is to avoid using Global variables.
Procedure.l	main(timeCheck.s = "")
	Protected	returnState.l
	
	; This is our linked list containing the time ranges...
	Protected NewList intervalList.timeInterval()
	
	; This is our item which will contain the return values, if available...
	Protected	returnItem.timeInterval
	
	
	; Let's add three elements to the linked list...
	AddElement(intervalList())
	intervalList()\intervalTag		= "Morning"
	intervalList()\intervalBegin	= "06:50"
	intervalList()\intervalEnd		= "08:30"

	AddElement(intervalList())
	intervalList()\intervalTag		= "Mid-Day"
	intervalList()\intervalBegin	= "12:15"
	intervalList()\intervalEnd		= "14:30"

	AddElement(intervalList())
	intervalList()\intervalTag		= "Afternoon"
	intervalList()\intervalBegin	= "17:10"
	intervalList()\intervalEnd		= "19:50"
	
	; If we have supplied a time, then supply the time to checkInterval, otherwise leave out the parameter...
	If (Len(Trim(timeCheck)) > 0)
		returnState	= checkInterval(intervalList(), returnItem, timeCheck)
	Else
		returnState	= checkInterval(intervalList(), returnItem)
	EndIf
	
	; If the return value is True, then we have a match, so display the range values...
	If (returnState)
		Debug "Match :" + returnItem\intervalTag + " , " + returnItem\intervalBegin + " , " + returnItem\intervalEnd
	Else
		Debug "No matching time range."
	EndIf
	
	ProcedureReturn returnState
	
EndProcedure



; ++++++++++++++++++++++++++++++++++++++++++++++++++
; ++++++++++++++++++++++++++++++++++++++++++++++++++


main()				; First time through...use the default computer time...
main("12:27")		; Second time through...let's supply our own time...


End


Posted: Fri Jul 20, 2007 3:14 am
by Dare
I have probably completely missed the point but here are some simple ways based on what I think you are asking:

Code: Select all

;Morning 6:50 - 8:30
;Mid-Day: 12:15 - 14:30
;Afternoon: 17:10 - 19:50 


testTime.s = "6:49"                              ; set up time to check

; Using strings

tmpStr.s = RSet(testTime.s,5,"0")                ; Assumes the format is "H:MM" or "HH:MM"

; With IF

If tmpStr >= "06:50" And tmpStr <= "08:30"
  Debug "Morning"
ElseIf tmpStr >= "12:15" And tmpStr <= "14:30"
  Debug "Mid-Day"
ElseIf tmpStr >= "17:10" And tmpStr <= "19:50"
  Debug "Afternoon"
Else
  Debug "Another time"
EndIf


; With integer

i = FindString(testTime,":",1)                   ; Assumes the format is "H:MM" or "HH:MM"
tmpInt = Val(Left(testTime,i-1)) * 60 + Val(Mid(testTime,i+1,2))

; With If

If tmpInt >= (6 * 60) + 50 And tmpInt <= (8 * 60) + 30
  Debug "Morning"
ElseIf tmpInt >= (12 * 60) + 15 And tmpInt <= (14 * 60) + 30
  Debug "Mid-Day"
ElseIf tmpInt >= (17 * 60) + 10 And tmpInt <= (19 * 60) + 50
  Debug "Afternoon"
Else
  Debug "Another time"
EndIf

; With Select

Select tmpInt
  Case 410 To 510                                 ; Mental arithmetic used .. may be out :)
    Debug "Morning"
  Case 735 To 870
    Debug "Mid-Day"
  Case 1030 To 1190
    Debug "Afternoon"
  Default
    Debug "Another time"
EndSelect
Obviously if the time is not in string format then Hour(testTime) and Minute(testTime) or whatever instead of the string bits.