DateDiff question

Just starting out? Need help? Post your questions and find answers here.
loulou2522
Enthusiast
Enthusiast
Posts: 549
Joined: Tue Oct 14, 2014 12:09 pm

DateDiff question

Post by loulou2522 »

Hi all
Is there a quick and simply way to calculate the difference in day between two date ?
ex 26/03/2021 compare with 24/03/2021 Result 2 days
Yhanks in advance
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: DateDiff question

Post by Josh »

Code: Select all

Debug (Date (2021, 03, 31, 00, 00, 00) -  Date (2021, 03, 29, 00, 00, 00)) / 60 / 60 / 24
sorry for my bad english
AZJIO
Addict
Addict
Posts: 2155
Joined: Sun May 14, 2017 1:48 am

Re: DateDiff question

Post by AZJIO »

Code: Select all

ImportC "msvcrt.lib"
	swprintf(*s, Format.s, Param1=0, Param2=0, Param3=0, Param4=0, Param5=0, Param6=0)
EndImport
Error_Procedure = 0

; AutoIt3 UDF
Procedure _DateIsLeapYear(Year)
	If Mod(Year, 4) = 0 And Mod(Year, 100) <> 0
		ProcedureReturn 1
	ElseIf Mod(Year, 400) = 0
		ProcedureReturn 1
	Else
		ProcedureReturn 0
	EndIf
EndProcedure

; @AZJIO
Procedure __DateDiff_2(Array Old(1), Array New(1), Array R(1))
	Protected i, t = 0, Dim L(5)
	L(0) = 5 ; не используется, размер массива
	L(1) = 12; месяцев в годе
	L(2) = 0 ; дней в месяце, определяется по условию
	L(3) = 24; часов в дне
	L(4) = 60; минут в часе
	L(5) = 60; секунд в минуте
	For i = 5 To 1 Step -1
		If i = 2
			Select Old(1)
				Case 1, 3, 5, 7, 8, 10, 12 ; месяца в которых 31 день
					L(i) = 31
				Case 2
					If _DateIsLeapYear(Old(0)) ; если високосный год, то в феврале:
						L(i) = 29
					Else
						L(i) = 28
					EndIf
				Default ; в остальных 30 дней
					L(i) = 30
			EndSelect
		EndIf
		; тут метод вычитания с заёмом
		If (New(i) - t) < Old(i)
			R(i) = New(i) + L(i) - t - Old(i)
			t = 1
		Else
			R(i) = New(i) - t - Old(i)
			t = 0
		EndIf
	Next
	R(0) = New(0) - Old(0) - t ; отдельно для годов
	ProcedureReturn
EndProcedure

; @AZJIO
Procedure.s DateDiff_2(Array Old(1), Array New(1))
	If ArraySize(Old()) < 5 ; проверка размера массива
		Error_Procedure = -1
		ProcedureReturn
	EndIf
	If ArraySize(New()) < 5
		Error_Procedure = -2
		ProcedureReturn
	EndIf
	Protected Extended = 0 ; дополнительный параметр, определяет что старая дата больше новой
	Protected Dim R(6)	   ; массив для результата
	R(0) = 0
	R(1) = 0
	R(2) = 0
	R(3) = 0
	R(4) = 0
	R(5) = 0
	; 	Цикл определяет какая дата больше или новее
	For i = 0 To 5
		If Old(i) <> New(i) ; если элементы не равны, то только тогда можно выявить старшинство, иначе переходим к младшему разряду - следующий шаг цикла
			If Old(i) < New(i) ; еслпи старая меньше (как и должно быть), то вызываем в первом параметре старый
				__DateDiff_2(Old(), New(), R())
			Else ; иначе вызываем новый как старый в первом параметре
				__DateDiff_2(New(), Old(), R())
				Extended = 1
			EndIf
			Break
		EndIf
	Next

	; 	Можно было бы переделать на возврат массива (по ссылке), но делаем строкой
	Protected Buff.s{100}
	swprintf(@Buff, "%d.%02d.%02d %02d:%02d:%02d", R(0), R(1), R(2), R(3), R(4), R(5))
	If Extended
		Buff = "-" + Buff
	EndIf
	ProcedureReturn Buff
EndProcedure

Dim date1(5)
date1(0) = 2018
date1(1) = 4
date1(2) = 12
date1(3) = 12
date1(4) = 30
date1(5) = 10

Dim date2(5)
date2(0) = 2019
date2(1) = 4
date2(2) = 12
date2(3) = 1
date2(4) = 31
date2(5) = 9
; не обязательно указывать дату, можно указать только время, тогда получим разницу только времени.
; смотрите также ParseDate(), обратную ей FormatDate() Date()
Debug DateDiff_2(date1(), date2()) ; в формате 12.03.24 04:16:14
User avatar
NicTheQuick
Addict
Addict
Posts: 1510
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: DateDiff question

Post by NicTheQuick »

I wonder when the Date library will finally be able to use 64 bit integers and dates after the year 2038.
I am also not able to make calculations with dates before 1970. I wish there were a second Date library natively which can do all of this.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
AZJIO
Addict
Addict
Posts: 2155
Joined: Sun May 14, 2017 1:48 am

Re: DateDiff question

Post by AZJIO »

For this to work on Linux, you need to replace the swprintf function

Format.pb

Code: Select all

XIncludeFile "Format.pb"
...
	Protected Buff.s
	Buff = Format( "%i.%02i.%02i %02i:%02i:%02i", @R(0), @R(1), @R(2), @R(3), @R(4), @R(5))
another option:

Code: Select all

ImportC ""
	sprintf(*str, format.p-utf8, Param1=0, Param2=0, Param3=0, Param4=0, Param5=0, Param6=0)
EndImport
...
	sprintf(@Buff, "%d.%02d.%02d %02d:%02d:%02d", R(0), R(1), R(2), R(3), R(4), R(5))
	Buff = PeekS(@Buff, -1, #PB_UTF8)
i did it based on my function
User avatar
DeanH
Enthusiast
Enthusiast
Posts: 274
Joined: Wed May 07, 2008 4:57 am
Location: Adelaide, South Australia
Contact:

Re: DateDiff question

Post by DeanH »

64-bit date functions are available. Wilbert posted a good set of procedures called Date64, and it has been updated by others. I have been using them successfully for several years. They cover years from 1582 to 9999.

http://www.purebasic.fr/english/viewtop ... 12#p421612

In order to calculate days apart, I convert regular gregorian date format to julian format and subtract. Julian dates are a number of days. I cannot recall where I first saw these but it was way back in the 1980's.

Code: Select all


;Convert gregorian date to julian
;Input D$ in DD/MM/YYYY format
Procedure.l GregorianToJulianDate(d$)
	Protected w,jg.l,b,mm,yy,dd,p,mm$
	dd=Val(Left(d$,2))
	mm=Val(Mid(d$,4,2))
	yy=Val(Right(d$,4))
	w=Int((mm-14)/12)
	jg=Int(1461*(yy+4800+w)/4)
	b=Int(367*(mm-2.-w*12)/12)
	jg=jg+b
	b=Int(Int(3*(yy+4900+w)/100)/4)
	jg=jg+dd-32075-b
	ProcedureReturn jg
EndProcedure

Procedure$ JulianToGregorianDate(jg.l)
	Protected w,r,z,n,dd,mm,yy
	w=jg+68569                           ;2520749
	r=Int(4*w/146097)                    ;69
	w=w-Int((146097*r+3)/4)           ;575
	z=Int(4000*(w+1)/1461001)          ;1
	w=w-Int(1461*z/4)+31              ;241
	n=Int(80*w/2447)                    ;7
	dd=w-Int(2447*n/80)                ;29   day
	w=Int(n/11)                          ;0
	mm=n+2-12*w                        ;9    month
	yy=100*(r-49)+z+w                 ;2001 year
	d$=RSet(Str(dd),2,"0")+"/"+RSet(Str(mm),2,"0")+"/"+Str(yy)
	ProcedureReturn d$
EndProcedure

;To get the difference between 25/03/2021 and 16/03/2021, use something like

jd1 = GregorianToJulianDate("25/03/2021")
jd2 = GregorianToJulianDate("16/03/2021")
Debug jd1
Debug jd2
DateDiff = Abs(jd1-jd2)
Debug DateDiff

;Should show in the debug window
;2459299
;2459290
;9

I'm sure the Date64 library could be used, too.
User avatar
mk-soft
Always Here
Always Here
Posts: 6226
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: DateDiff question

Post by mk-soft »

Only Windows ...

Code: Select all

Procedure SetDateToSystemTime(vTime.d,*Time.SystemTime)
  Protected r1
  r1 = VariantTimeToSystemTime_(vTime, *Time)
  ProcedureReturn r1
EndProcedure

Procedure.d GetDateFromSystemTime(*Time.SystemTime)
  Protected r1, vTime.d
  r1 = SystemTimeToVariantTime_(*Time, @vTime)
  ProcedureReturn vtime
EndProcedure

Procedure SetSystemTime(*Time.SystemTime, Year, Month, Day, Hour = 0, Minute = 0, Second = 0)
  With *Time
    \wYear = Year
    \wMonth = Month
    \wDay = Day
    \wHour = Hour
    \wMinute = Minute
    \wSecond = Second
    \wMilliseconds = 0
  EndWith
EndProcedure


Global systime1.SystemTime  
Global systime2.SystemTime  
Global date1.d, date2.d, date3.d

GetLocalTime_(systime1)
SetSystemTime(systime2, 1965, 08, 20, 15, 30)

date1 = GetDateFromSystemTime(systime1)
date2 = GetDateFromSystemTime(systime2)
date3 = date1 - date2
Debug "I am " + StrD(date3, 2) + " days old"
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
mk-soft
Always Here
Always Here
Posts: 6226
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: DateDiff question

Post by mk-soft »

For macOS ...

Code: Select all

;-TOP

; ----

;- MacOS Date funtions

; Mask:
;   Year   = yyyy
;   Month  = MM (1..12), MMM (Short Name), MMMM (Long Name)
;   Day    = dd
;   Hour   = HH (0..23), hh (0..11); a = period (AM, PM)
;   Minute = mm
;   Second = ss
;   
;   Day ot the year   = DDD (1..3)
;   Week of Year      = ww
;   Week of Month     = W

Macro CocoaString(NSString)
  PeekS(CocoaMessage(0, NSString, "UTF8String"), -1, #PB_UTF8)
EndMacro

Procedure.s GetStringFromDate(Date, Mask.s = "yyyy-MM-dd")
  Protected NSPool, NSDateFormatter, NSString
  Protected r1.s
  
  NSPool = CocoaMessage(0, 0, "NSAutoreleasePool new")
  NSDateFormatter = CocoaMessage(0, 0, "NSDateFormatter new")
  
  ; Convert PB date format
  If FindString(Mask, "%")
    mask = LCase(mask)
    mask = ReplaceString(mask, "m", "M")
    mask = ReplaceString(mask, "i", "m")
    mask = ReplaceString(mask, "h", "H")
    mask = RemoveString(mask, "%")
  EndIf
    
  If Date = 0
    Date = CocoaMessage(0, 0, "NSDate date")
  EndIf
  
  CocoaMessage(0, NSDateFormatter, "setDateFormat:$", @Mask)
  NSString = CocoaMessage(0, NSDateFormatter, "stringFromDate:@", @Date)
  r1 = CocoaString(NSString)
  
  CocoaMessage(0, NSDateFormatter, "release")
  CocoaMessage(0, NSPool, "release")
  
  ProcedureReturn r1
EndProcedure

Procedure GetDateFromString(Date.s = "now", Mask.s = "yyyy-MM-dd")
  Protected NSPool, NSDate, NSDateFormatter
  Protected r1
  
    
  NSPool = CocoaMessage(0, 0, "NSAutoreleasePool new")
  NSDateFormatter = CocoaMessage(0, 0, "NSDateFormatter new")
  
  If date = "now"
    r1 = CocoaMessage(0, 0, "NSDate now")
  Else
    ; Convert PB date format
    If FindString(Mask, "%")
      mask = LCase(mask)
      mask = ReplaceString(mask, "m", "M")
      mask = ReplaceString(mask, "i", "m")
      mask = ReplaceString(mask, "h", "H")
      mask = RemoveString(mask, "%")
    EndIf
    
    CocoaMessage(0, NSDateFormatter, "setDateFormat:$", @Mask)
    r1 = CocoaMessage(0, NSDateFormatter, "dateFromString:$", @Date)
  EndIf
  CocoaMessage(0, NSDateFormatter, "release")
  CocoaMessage(0, NSPool, "release")
  
  ProcedureReturn r1
EndProcedure

; ----

Define diff.d

Define date1 = GetDateFromString()
Define date2 = GetDateFromString("1965-08-20 15:30:00", "%YYYY-%MM-%DD %HH:%II:%SS")
;Define date2 = CocoaMessage(0, 0, "NSDate dateWithString:$", @"1965-08-20 14:30:00 +0000")

Debug GetStringFromDate(date1, "%YYYY-%MM-%DD %hh:%II:%SS")
Debug GetStringFromDate(date2, "%YYYY-%MM-%DD %hh:%II:%SS")

r1 = CocoaMessage(@diff, date1, "timeIntervalSinceDate:", date2)
Debug "I am " + StrD(diff / 86400.0, 2) + " days old"
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Post Reply