Page 1 of 1

How to manipulate dates on a text file?

Posted: Fri Jul 28, 2023 3:23 pm
by dcr3
Hi. I want manipulate dates on a text file, according to some rules.
What is the best way, either with regex or any other method.

E.G:
28/07/2023 > 2023/07/28 or 2023/Jul/28 or 2023-Jul-28
2023.07.20 > 28.07.2023 or 2023 Jul 28
2023 Jul, 28 > 2023 07 28 or 2023/07/28

Etc....Etc..

Code: Select all

;If CreateRegularExpression(0, "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)(?=[\s\S](\d+))\s(\d{2}),\s(\d{4})") ;Good
;If CreateRegularExpression(0, "(\d{2}[- /.])(\d{2}[- /.])(\d{4})")
;If CreateRegularExpression(0, "(\d{2}[- /.])(\d{2}[- /.])(\d{4}[- /.])")
 If CreateRegularExpression(0, "(\d{4})([- /.]\d{2})([- /.]\d{2})")

;If CreateRegularExpression(0, "((\d{2}[- /.])(\d{2}[- /.])(\d{4})|(\d{4})([- /.]\d{2})([- /.]\d{2}))") 
  count = CountRegularExpressionGroups(0)
  Debug count
  Dim expcount.s(count)
  If ExamineRegularExpression(0,text$)
    While NextRegularExpressionMatch(0)
      For x=1 To count
        expcount.s(x)=RegularExpressionGroup(0, x)
        Debug expcount.s(x) +" :> "+x
      Next
    Wend
    If count=3;count=7
      
      Define Result.s = ReplaceRegularExpression(0,text$, expcount.s(3)+expcount.s(2)+expcount.s(1))
     ; Define Result.s = ReplaceRegularExpression(0,text$, expcount.s(5)+expcount.s(7)+expcount.s(6))
      Debug "Before : "+text$ + " After :"+Result 
    ElseIf count=4
      Define Result.s = ReplaceRegularExpression(0,text$, expcount.s(4)+"-"+expcount.s(3)+"-"+expcount.s(1))
      Debug "Before : "+text$ + " After :"+Result
    EndIf
    
  EndIf
EndIf

Re: How to manipulate dates on a text file?

Posted: Fri Jul 28, 2023 5:16 pm
by jacdelad
What do you mean with "manipulate dates on a text file"? Do you mean the content or the date of the file?
Assuming you mean the content: Will the input always be the same or at least be in one of some shapes? If yes, I would use RegEx.
However, it will be hard to distinguish american and european dates (if the separators aren't always clearly different): what is 04.02.2023?

Re: How to manipulate dates on a text file?

Posted: Fri Jul 28, 2023 5:45 pm
by dcr3
jacdelad wrote: Fri Jul 28, 2023 5:16 pm Do you mean the content
Yeah. :shock: I am aware of many tools to change time and dates on a file.

dcr3 wrote: Fri Jul 28, 2023 3:23 pm E.G:
28/07/2023 > to 2023/07/28 or 2023/Jul/28 or 2023-Jul-28
2023.07.20 > 28.07.2023 or 2023 Jul 28
2023 Jul, 28 > 2023 07 28 or 2023/07/28

Etc....Etc..

Re: How to manipulate dates on a text file?

Posted: Fri Jul 28, 2023 6:01 pm
by AZJIO
The number of groups depends on the pattern in the regular expression, not on the number of matches found. If a group is given that may not be found (.*?), then it is returned empty.
You can use StringField(str, 1, "\") or SplitL2(str, List.s(), "-/.")

The regular expression does not change any of these elements (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) to a number. The regular expression adds 150 kb to the program. If you can write code without it, then do so.

02/04/2023 - you don't know where is the day and where is the month. In our country 02 is a day, in Europe 02 is a month
28.07.23 - we allow this.

Re: How to manipulate dates on a text file?

Posted: Fri Jul 28, 2023 9:33 pm
by infratec
To be flexible you need to convert your search mask to a regex.

Maybe something like this:

Code: Select all

; 
; D(D) Day
; M(M) Month
; YY(YY) Year
; MO Month as name

Procedure.s CreateDateRegex(DateMask$)
  
  Protected.i Len, Pos
  Protected RegEx$, Char$
  
  
  Len = Len(DateMask$)
  Pos = 1
  While Pos <= Len
    Char$ = Mid(DateMask$, Pos, 1)
    Select Char$
      Case "D"
        If Mid(DateMask$, Pos + 1, 1) = "D"
          RegEx$ + "[0-2][0-9]"
          Pos + 1
        Else
          RegEx$ + "\d+"
        EndIf
      Case "M"
        If Mid(DateMask$, Pos + 1, 1) = "M"
          RegEx$ + "[01][0-9]"
          Pos + 1
        Else
          If Mid(DateMask$, Pos + 1, 1) = "O"
            RegEx$ + "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"
            Pos + 1
          Else
            RegEx$ + "\d+"
          EndIf
        EndIf
      Case "Y"
        If Mid(DateMask$, Pos, 4) = "YYYY"
          RegEx$ + "\d{4}"
          Pos + 3
        Else
          RegEx$ + "\d{2}"
          Pos + 1
        EndIf
        
      Default
        If Char$ = " "
          RegEx$ + "\s"
        Else
          If Char$ = "/" Or Char$ = "."
            RegEx$ + "\" + Char$
          Else
            RegEx$ + Char$
          EndIf
        EndIf
    EndSelect
    Pos + 1
  Wend
  
  ProcedureReturn RegEx$
  
EndProcedure

Debug CreateDateRegex("YYYY/MM/DD")
Debug CreateDateRegex("DD MO YYYY")
Debug CreateDateRegex("DD.MM.YYYY")
Then, if you find something, you can convert it with a target mask.

Re: How to manipulate dates on a text file?

Posted: Fri Jul 28, 2023 9:59 pm
by dcr3
AZJIO wrote: Fri Jul 28, 2023 6:01 pm The number of groups depends on the pattern in the regular expression, not on the number of matches found. If a group is given that may not be found (.*?), then it is returned empty.
Thanks for the tips.
AZJIO wrote: Fri Jul 28, 2023 6:01 pm The regular expression adds 150 kb to the program. If you can write code without it, then do so.
I will keep that in mind.
AZJIO wrote: Fri Jul 28, 2023 6:01 pm You can use StringField(str, 1, "\") or SplitL2(str, List.s(), "-/.")

I have being trying, but not very successful.



Thanks. Infratec.I will try to figure out and how to adapt you code. :)

Re: How to manipulate dates on a text file?

Posted: Fri Jul 28, 2023 10:59 pm
by AZJIO
dcr3 wrote: Fri Jul 28, 2023 9:59 pm I have being trying, but not very successful.

Code: Select all

; https://www.purebasic.fr/english/viewtopic.php?p=585485#p585485
Procedure SplitL2(String$, List StringList.s(), Separator$ = #CRLF$ + #TAB$ + #FF$ + #VT$ + " ")
	Protected *S.Integer = @String$
	Protected *jc.Character, *c.Character = @String$
	
	ClearList(StringList())
	
	While *c\c
		*jc = @Separator$
		
		While *jc\c
			If *c\c = *jc\c
				*c\c = 0
				If *S <> *c
					AddElement(StringList())
					StringList() = PeekS(*S)
					;                     StringList() = PeekS(*S, (*c - *S) >> 1)
				EndIf
				*S = *c + SizeOf(Character)
				Break
			EndIf
			*jc + SizeOf(Character)
		Wend
		
		*c + SizeOf(Character)
	Wend
	AddElement(StringList())
	StringList() = PeekS(*S)
EndProcedure

Global Dim Month3.s(12)
Month3(1) = "Jan"
Month3(2) = "Feb"
Month3(3) = "Mar"
Month3(4) = "Apr"
Month3(5) = "May"
Month3(6) = "Jun"
Month3(7) = "Jul"
Month3(8) = "Aug"
Month3(9) = "Sep"
Month3(10) = "Oct"
Month3(11) = "Nov"
Month3(12) = "Dec"

Global Dim MonthLong.s(12)
Month3(1) = "January"
Month3(2) = "February"
Month3(3) = "March"
Month3(4) = "April"
Month3(5) = "May"
Month3(6) = "June"
Month3(7) = "July"
Month3(8) = "August"
Month3(9) = "September"
Month3(10) = "October"
Month3(11) = "November"
Month3(12) = "December"

; Define S.s = "2023.7.20"
; Define S.s = "2023.May.20"
Define S.s = "2023.February.20"
Define NewList MyStrings.s()

SplitL2(S, MyStrings(), "-/. ")
ForEach MyStrings()
	Debug MyStrings()
Next

S = ""
ResetList(MyStrings())
While NextElement(MyStrings())
	S + MyStrings() + " — "
Wend
S = Left(S, Len(S) - 3)
Debug S

Define i
Define Y.s, M.s, D.s
ResetList(MyStrings())
NextElement(MyStrings())
Y = MyStrings()
NextElement(MyStrings())
M = MyStrings()
If Len(M) = 3
	For i = 1 To 12
		If M = Month3(i)
			M = Str(i)
			Break
		EndIf
	Next
EndIf
If Len(M) > 3
	For i = 1 To 12
		If M = MonthLong(i)
			M = Str(i)
			Break
		EndIf
	Next
EndIf
NextElement(MyStrings())
D = MyStrings()
Debug D + "*" + M + "*" + Y

Re: How to manipulate dates on a text file?

Posted: Fri Jul 28, 2023 11:30 pm
by AZJIO
This might also come in handy

Code: Select all

; AZJIO
; Formatted string for date output
Procedure.s TrimLeft(String$, n)
	ProcedureReturn Right(String$, Len(String$) - n)
EndProcedure


Procedure.s _DateTime(FormStr$, DateCurSec = 0)
	; дата в массив
	Protected Dim DateCur(6), Dim MON.s(12), Dim WDAY.s(6), Dim WDAY2.s(6)

	If Not DateCurSec
		DateCurSec = Date()
	EndIf

	DateCur(0) = Year(DateCurSec)
	DateCur(1) = Month(DateCurSec)
	DateCur(2) = Day(DateCurSec)
	DateCur(3) = Hour(DateCurSec)
	DateCur(4) = Minute(DateCurSec)
	DateCur(5) = Second(DateCurSec)
	DateCur(6) = DayOfWeek(DateCurSec)

	FormStr$ = ReplaceString(FormStr$, "\n", #CRLF$) ; переносы строк
	FormStr$ = ReplaceString(FormStr$, "yyyy", Str(DateCur(0))) ; год 4 символа
	FormStr$ = ReplaceString(FormStr$, "yy", TrimLeft(Str(DateCur(0)), 2)) ; год 2 символа

; 	MON(1) = "Январь"
; 	MON(2) = "Февраль"
; 	MON(3) = "Март"
; 	MON(4) = "Апрель"
; 	MON(5) = "Май"
; 	MON(6) = "Июнь"
; 	MON(7) = "Июль"
; 	MON(8) = "Август"
; 	MON(9) = "Сентябрь"
; 	MON(10) = "Октябрь"
; 	MON(11) = "Ноябрь"
; 	MON(12) = "Декабрь"
	MON(1) = "January"
	MON(2) = "February"
	MON(3) = "March"
	MON(4) = "April"
	MON(5) = "May"
	MON(6) = "June"
	MON(7) = "July"
	MON(8) = "August"
	MON(9) = "September"
	MON(10) = "October"
	MON(11) = "November"
	MON(12) = "December"

	FormStr$ = ReplaceString(FormStr$, "MMMM", MON(DateCur(1)), #PB_String_CaseSensitive, 1, 1)
	FormStr$ = ReplaceString(FormStr$, "mmmm", LCase(MON(DateCur(1))), #PB_String_CaseSensitive, 1, 1)
	FormStr$ = ReplaceString(FormStr$, "MMM", Left(MON(DateCur(1)), 3), #PB_String_CaseSensitive, 1, 1)
	FormStr$ = ReplaceString(FormStr$, "mmm", LCase(Left(MON(DateCur(1)), 3)), #PB_String_CaseSensitive, 1, 1)
	FormStr$ = ReplaceString(FormStr$, "mm", RSet(Str(DateCur(1)), 2, "0"))
	FormStr$ = ReplaceString(FormStr$, "dd", RSet(Str(DateCur(2)), 2, "0"))

; 	WDAY(0) = "Воскресенье"
; 	WDAY(1) = "Понедельник"
; 	WDAY(2) = "Вторник"
; 	WDAY(3) = "Среда"
; 	WDAY(4) = "Четверг"
; 	WDAY(5) = "Пятница"
; 	WDAY(6) = "Суббота"
	
	WDAY(0) = "Sunday"
	WDAY(1) = "Monday"
	WDAY(2) = "Tuesday"
	WDAY(3) = "Wednesday"
	WDAY(4) = "Thursday"
	WDAY(5) = "Friday"
	WDAY(6) = "Saturday"

; 	WDAY2(0) = "Вс"
; 	WDAY2(1) = "Пн"
; 	WDAY2(2) = "Вт"
; 	WDAY2(3) = "Ср"
; 	WDAY2(4) = "Чт"
; 	WDAY2(5) = "Пт"
; 	WDAY2(6) = "Сб"

	WDAY2(0) = "Sun"
	WDAY2(1) = "Mon"
	WDAY2(2) = "Tue"
	WDAY2(3) = "Wed"
	WDAY2(4) = "Thur"
	WDAY2(5) = "Fri"
	WDAY2(6) = "Sat"

; 	WDAY2(0) = "Su"
; 	WDAY2(1) = "Mo"
; 	WDAY2(2) = "Tu"
; 	WDAY2(3) = "We"
; 	WDAY2(4) = "Th"
; 	WDAY2(5) = "Fr"
; 	WDAY2(6) = "Sa"
	

	FormStr$ = ReplaceString(FormStr$, "WWW", WDAY(DateCur(6)), #PB_String_CaseSensitive, 1, 1)
	FormStr$ = ReplaceString(FormStr$, "www", LCase(WDAY(DateCur(6))), #PB_String_CaseSensitive, 1, 1)
	FormStr$ = ReplaceString(FormStr$, "WW", WDAY2(DateCur(6)), #PB_String_CaseSensitive, 1, 1)
	FormStr$ = ReplaceString(FormStr$, "ww", LCase(WDAY2(DateCur(6))), #PB_String_CaseSensitive, 1, 1)
	FormStr$ = ReplaceString(FormStr$, "hh", RSet(Str(DateCur(3)), 2, "0"))
	FormStr$ = ReplaceString(FormStr$, "ii", RSet(Str(DateCur(4)), 2, "0"))
	FormStr$ = ReplaceString(FormStr$, "ss", RSet(Str(DateCur(5)), 2, "0"))
	ProcedureReturn FormStr$
EndProcedure

; FormatDate("%yyyy.%mm.%dd %hh:%ii:%ss", Date())
res$ = ""
res$ +_DateTime("The current date: yyyy.mm.dd hh:ii:ss\n")
res$ +_DateTime("day of the week: WWW\n")
res$ +_DateTime("briefly: MMM.dd hh:ii\n")
res$ +_DateTime("informatively: dd WW hh:ii")
MessageRequester("Message", res$)

Re: How to manipulate dates on a text file?

Posted: Sat Jul 29, 2023 12:03 am
by dcr3
@AZJIO.

If the dates where at the beginning of text file, then that approach could be viable.

But there not.

Something like this.

textread.s=" Bla bla bla bla 28-07-2023 bla bla ...etc.."



If all the dates where at the beginning.
Then I could simply do something like this.

Code: Select all

 textread.s="28-07-2023"
;textread.s="28.07.2023"
;textread.s="28/07/2023"
;textread.s="28 Jul 2023"
Dim Swap_dmy.s(1)
For i =1 To Len(textread) 
  For v=0 To 1    
    If i=1
      Swap_dmy(0)= Mid(textread, i, 3)
      Break
    ElseIf i=4
      Swap_dmy(1)= Mid(textread, i, 3) 
      Break
    EndIf
  Next
Next
Debug ReplaceString(textread.s,Swap_dmy(0)+Swap_dmy(1),Swap_dmy(1)+Swap_dmy(0))



Re: How to manipulate dates on a text file?

Posted: Sat Jul 29, 2023 12:28 am
by AZJIO
I can't read minds.
28/07/2023 > 2023/07/28 or 2023/Jul/28 or 2023-Jul-28
This line implies the conversion of dates, but does not say that they should be found in the text.
The variable "text$" is also not defined in the example.
There are a lot of types of regular expressions, some check the validity of data, others modify, others search. Validation checkers will be different from regular expressions that perform searches.

If you are writing a private tool and not a public program, then of course you don't need to think about size, speed and beauty. You can use regular expressions and not bother with writing a complex algorithm that repeats the regular expression engine.

In this example, the length of found and replaced are the same, so there is no shift in position after the replacement. It is possible to use #PB_String_InPlace.

Code: Select all

EnableExplicit
#oREx = 0

Global Text$
Global gr1$, gr2$, gr3$, re$

#File = 0
If ReadFile(#File, "C:\1.txt")
	Text$ = ReadString(#File, #PB_File_IgnoreEOL)
	CloseFile(#File)
EndIf

Debug Text$

If CreateRegularExpression(#oREx, "(\d{4}|\d{2})([/. -])(\d{2}|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\2(\d{4}|\d{2})", 0)
	If ExamineRegularExpression(#oREx, Text$)
		While NextRegularExpressionMatch(#oREx)
			gr1$ = RegularExpressionGroup(#oREx, 1)
			gr2$ = RegularExpressionGroup(#oREx, 3)
			gr3$ = RegularExpressionGroup(#oREx, 4)
			If Len(gr1$) = 4
				re$ = gr3$ + "|" + gr2$ + "|"  + gr1$
; 			ElseIf Len(gr3$) = 4
			Else
				re$ = gr1$ + "|" + gr2$ + "|"  + gr3$
			EndIf
			Text$ = ReplaceString(Text$, RegularExpressionMatchString(#oREx), re$, 
			                      #PB_String_CaseSensitive, RegularExpressionMatchPosition(#oREx), 1)
; 			ReplaceString(Text$, RegularExpressionMatchString(#oREx), re$, 
; 			                      #PB_String_CaseSensitive | #PB_String_InPlace, RegularExpressionMatchPosition(#oREx), 1)
		Wend
	EndIf
Else
	Debug RegularExpressionError()
EndIf

Debug Text$

Re: How to manipulate dates on a text file?

Posted: Sat Jul 29, 2023 2:29 pm
by mk-soft
Only Windows (API) ...

Code: Select all

;- TOP by mk-soft

#DT_BASE_1970 = 25569.0

Procedure GetDateFromString(Date.s)
  Protected r1.l, varBSTR.VARIANT, varDate.Variant, time.d
  
  varBSTR\vt = #VT_BSTR
  varBSTR\bstrVal = SysAllocString_(Date)
  r1 = VariantChangeType_(varDate, varBSTR, 0, #VT_DATE)
  VariantClear_(varBSTR)
  If r1 = #S_OK
    time = (varDate\date - #DT_BASE_1970) * 86400.0
    ProcedureReturn time
  Else
    ProcedureReturn -1
  EndIf
EndProcedure

Define date.i

date = GetDateFromString("28-07-2023")
Debug FormatDate("%YYYY-%MM-%DD", date)

date = GetDateFromString("28.07.2023")
Debug FormatDate("%YYYY-%MM-%DD", date)

date = GetDateFromString("28/07/2023")
Debug FormatDate("%YYYY-%MM-%DD", date)

date = GetDateFromString("28 Jul 2023")
Debug FormatDate("%YYYY-%MM-%DD", date)

Re: How to manipulate dates on a text file?

Posted: Sat Jul 29, 2023 9:36 pm
by dcr3
AZJIO wrote: Sat Jul 29, 2023 12:28 am I can't read minds.
Some times it just a matter of rereading the post.
dcr3 wrote: Fri Jul 28, 2023 5:45 pm jacdelad wrote: ↑Fri Jul 28, 2023 5:16 pm
Do you mean the content

Yeah. :shock: I am aware of many tools to change time and dates on a file.
.
AZJIO wrote: Sat Jul 29, 2023 12:28 am There are a lot of types of regular expressions, some check the validity of data, others modify, others search. Validation checkers will be different from regular expressions that perform searches.
I am trying to get the grip , I am getting a better picture.


Thanks for your input, very much appreciated.

You are, a very good coder and have lots of good code to learn from. :D

Re: How to manipulate dates on a text file?

Posted: Sat Jul 29, 2023 9:42 pm
by dcr3
mk-soft wrote: Sat Jul 29, 2023 2:29 pm ;- TOP by mk-soft

#DT_BASE_1970 = 25569.0

Procedure GetDateFromString(Date.s)
Protected r1.l, varBSTR.VARIANT, varDate.Variant, time.d

varBSTR\vt = #VT_BSTR
varBSTR\bstrVal = SysAllocString_(Date)
r1 = VariantChangeType_(varDate, varBSTR, 0, #VT_DATE)
VariantClear_(varBSTR)
If r1 = #S_OK
time = (varDate\date - #DT_BASE_1970) * 86400.0
ProcedureReturn time
Else
ProcedureReturn -1
EndIf
EndProcedure

Define date.i

date = GetDateFromString("28-07-2023")
Debug FormatDate("%YYYY-%MM-%DD", date)

date = GetDateFromString("28.07.2023")
Debug FormatDate("%YYYY-%MM-%DD", date)

date = GetDateFromString("28/07/2023")
Debug FormatDate("%YYYY-%MM-%DD", date)

date = GetDateFromString("28 Jul 2023")
Debug FormatDate("%YYYY-%MM-%DD", date)

Ok. Interesting.

But can't parse this date.

Code: Select all

date = GetDateFromString("28.07.2023")
Debug FormatDate("%YYYY-%MM-%DD", date)
Why is there a limit on date up to 19-01-2038. :idea:

Code: Select all

;This is the limit.
date = GetDateFromString("19-01-2038")
Debug FormatDate("%YYYY-%MM-%DD", date)

Code: Select all

;This does not parse.
date = GetDateFromString("20-01-2038")
Debug FormatDate("%YYYY-%MM-%DD", date)

Code: Select all

DD$="29.06.2035":DATE1.i=ParseDate("%dd.%mm.%yyyy",DD$)
Debug FormatDate("%YYYY.%MM.%DD", DATE1)

SLD$="20/09/2025":DATE2.i=ParseDate("%dd/%mm/%yyyy",SLD$)
Debug FormatDate("%YYYY/%MM/%DD", DATE2)

sPD$="02 05 2026":DATE3.i=ParseDate("%dd %mm %yyyy",sPD$)
Debug FormatDate("%YYYY %MM %DD", DATE3)
Debug FormatDate("%YYYY %DD %MM", DATE3)
HD$="12-08-2027":DATE4.i=ParseDate("%dd-%mm-%yyyy",HD$)
Debug FormatDate("%YYYY-%MM-%DD", DATE4)

Re: How to manipulate dates on a text file?

Posted: Sat Jul 29, 2023 10:09 pm
by infratec

Re: How to manipulate dates on a text file?

Posted: Sat Jul 29, 2023 10:36 pm
by dcr3

Thanks for link. I wasn't aware. A very interesting read. :D