set the ZBasic VM's date/time using windows command line

Here you can share completed projects or parts of projects that may be useful to others. You may post files relevant to ZBasic - source code, schematics, etc.
Post Reply
stevech
Posts: 715
Joined: 22 February 2006, 20:56 PM

set the ZBasic VM's date/time using windows command line

Post by stevech »

Here's a ditty that can be helpful if you need to set the ZX module's date and time to match that of a PC's clock.

This code accepts, on the console serial port input, a line of text that comes from a Windows "date" command line as shown below. This ZBasic code then parses the date time from this and sets the ZBasic Virtual Machine (VM) date and time.

The Windows command line begins with "d-8". This ("d") can be used by the application to detect that the date command follows. The -8 is parsed as the GMT offset in hours, for applications that automatically adjust daylight savings time or calculate GMT and local time.

The parsing code may need tweaking if you are in a country where your date/time formats differ.

Can't redirect the echo command's output directly to a com port on the PC because the port opens and the data flows before the ZBasic VM has finished resetting due to the change in DTR on the port. You can cut/paste the echo command's output into the debug window of the IDE. Or write a PC program that opens the com port and sends this data as from the echo command.

Code: Select all

''''''''''''''''''''''''''''''''''''''''''''''''''''''
' echo d-8 %date% %time%      Windows command in batch file yields...
' column numbers. second set is relative to i
'         0000000001111111112222  
' 1234    0123456789012345678901	
' d-8 Fri 10/06/2006 20&#58;46&#58;15.32	 result of echo commmand, above. hr has leading space if < 10. 24 hr clock

function SetDateTime&#40;s as string&#41; as boolean
	dim i as byte
	dim mm as byte, d as byte, y as integer
	dim h as byte, m as byte, secs as single
	
	GMToffset = atoi&#40;mid&#40;s,2,3&#41;&#41;
	i=5 ' skip over GMT offset
	do while not isnumeric&#40;mid&#40;s,i,1&#41;&#41;
		i=i+1
	loop
	mm = cbyte&#40;atoi&#40;mid&#40;s,i+0,2&#41;&#41;&#41;
	d = cbyte&#40;atoi&#40;mid&#40;s,i+3,2&#41;&#41;&#41;
	y = atoi&#40;mid&#40;s,i+6,4&#41;&#41;
	h = cbyte&#40;atoi&#40;mid&#40;s,i+11,2&#41;&#41;&#41;
	m = cbyte&#40;atoi&#40;mid&#40;s,i+14,2&#41;&#41;&#41;
	call valueS&#40;mid&#40;s,i+17, 5&#41;, secs, SetDateTime&#41;
	
	''' set date time in the VM
	call PutTimeStamp&#40;y, mm, d, h, m, secs&#41;
	'''debug.print cstr&#40;GMToffset&#41;;" ";cstr&#40;mm&#41;;" ";cstr&#40;d&#41;;" ";cstr&#40;y&#41;;" ";cstr&#40;h&#41;;" ";cstr&#40;m&#41;;" ";cstr&#40;secs&#41;
end function	
'''''''''''''''''''''''''''''''''''''''''''''''''''''
function isnumeric&#40;byval s1 as string&#41; as BOOLEAN
	dim b as byte
	
	b = asc&#40;mid&#40;s1,1,1&#41;&#41;
	if b >= asc&#40;"0"&#41; and b <= asc&#40;"9"&#41; then
		isnumeric = TRUE
	else
		isnumeric = FALSE
	end if
end function
'''''''''''''''''''''''''''''''''''''''''''''''''''''
function atoi&#40;byval s1 as string&#41; as integer
	dim ok as BOOLEAN
	dim v as single
	
	'debug.print "atoi ";s1
	call valueS&#40;s1, v, ok&#41;
	if &#40;ok&#41; then
		atoi = cint&#40;fix&#40;v&#41;&#41;
	else
		atoi = 0
	end if
end function
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

Great idea.

I might suggest changing IsNumeric() to take a Byte parameter. In this particular use case that would avoid unnecessarily creating 1 byte strings and some compiler generated temporary variables to hold them. The implementation could then be:

Code: Select all

Function IsNumeric&#40;ByVal b as Byte&#41; as Boolean
    IsNumeric = &#40;b >= asc&#40;"0"&#41;&#41; And &#40;b <= asc&#40;"9"&#41;&#41;
End Function 
Then, the invocation would be:

Code: Select all

Do While Not IsNumeric&#40;Chr&#40;s, i&#41;&#41;
- Don Kinzer
stevech
Posts: 715
Joined: 22 February 2006, 20:56 PM

Post by stevech »

thanks. will do.
wouldn't that have to be coded

IsNumeric(Asc(mid(s, i, 1)))
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

Actually, it should have been:

Code: Select all

IsNumeric&#40;Asc&#40;s, i&#41;&#41;
The optional second parameter to Asc() allows you to retrieve a particular character from a string without having to use Mid() as an intermediary.
- Don Kinzer
stevech
Posts: 715
Joined: 22 February 2006, 20:56 PM

Post by stevech »

here's the code with the changes discussed above...

Code: Select all

''''''''''''''''''''''''''''''''''''''''''''''''''''''
' echo d-8 %date% %time%      Windows command in batch file yields...
' column numbers. second set is relative to i
'         0000000001111111112222  
' 1234    0123456789012345678901	
' d-8 Fri 10/06/2006 20&#58;46&#58;15.32	 result of echo commmand, above. hr has leading space if < 10. 24 hr clock

function SetDateTime&#40;s as string&#41; as boolean
	dim i as byte
	dim mm as byte, d as byte, y as integer
	dim h as byte, m as byte, secs as single
	
	GMToffset = atoi&#40;mid&#40;s,2,3&#41;&#41;
	i=5 ' skip over GMT offset
	do while not IsNumeric&#40;Asc&#40;s, i&#41;&#41;
		i=i+1
	loop
	mm = cbyte&#40;atoi&#40;mid&#40;s,i+0,2&#41;&#41;&#41;
	d = cbyte&#40;atoi&#40;mid&#40;s,i+3,2&#41;&#41;&#41;
	y = atoi&#40;mid&#40;s,i+6,4&#41;&#41;
	h = cbyte&#40;atoi&#40;mid&#40;s,i+11,2&#41;&#41;&#41;
	m = cbyte&#40;atoi&#40;mid&#40;s,i+14,2&#41;&#41;&#41;
	call valueS&#40;mid&#40;s,i+17, 5&#41;, secs, SetDateTime&#41;
	
	''' set date time in the VM
	call PutTimeStamp&#40;y, mm, d, h, m, secs&#41;
	'''debug.print cstr&#40;GMToffset&#41;;" ";cstr&#40;mm&#41;;" ";cstr&#40;d&#41;;" ";cstr&#40;y&#41;;" ";cstr&#40;h&#41;;" ";cstr&#40;m&#41;;" ";cstr&#40;secs&#41;
end function	
'''''''''''''''''''''''''''''''''''''''''''''''''''''
Function IsNumeric&#40;ByVal b as Byte&#41; as Boolean
    IsNumeric = &#40;b >= asc&#40;"0"&#41;&#41; And &#40;b <= asc&#40;"9"&#41;&#41;
End Function
'''''''''''''''''''''''''''''''''''''''''''''''''''''
function atoi&#40;byval s1 as string&#41; as integer
	dim ok as BOOLEAN
	dim v as single
	
	'debug.print "atoi ";s1
	call valueS&#40;s1, v, ok&#41;
	if &#40;ok&#41; then
		atoi = cint&#40;fix&#40;v&#41;&#41;
	else
		atoi = 0
	end if
end function
stevech
Posts: 715
Joined: 22 February 2006, 20:56 PM

Post by stevech »

EDIT: I added in the comments some VBscript code to output date/time.

Here's a recode of the function to parse the date/time from a string as would come from the serial port and a windows batch file or a VBScript. And then put the date/time into the ZBasic VM.

This version accepts varied formats, such as

d-8 10/21/06 8:13:12.34 PM
and
d-8 12/21/2006 20:13:12.34

There's also a couple of number conversion functions that by themselves might be useful.

Code: Select all

''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
' VBscript&#58; 
	'on error resume next
	'~ GMToffset = "d-8"
	
	'~ Set com_port = CreateObject&#40;"MSCOMMLib.MSComm"&#41;
	'~ com_port.commport = 4
	'~ com_port.settings = "19200,N,8,1"
	'~ com_port.RThreshold = 0
	
	'~ com_port.PortOpen = True
	'~ if com_port.PortOpen = true then
	'~ wsh.sleep&#40;3000&#41;
	'~ do 
		'~ s = com_port.Input
		'~ wsh.sleep&#40;200&#41;
	'~ loop while s <> ""
	'~ s = GMToffset & " " & FormatDateTime&#40;now&#40;&#41;,0&#41; & vbcrlf
	'~ com_port.output = s
	'~ wsh.sleep&#40;500&#41;
	'~ com_port.PortOpen = False
	'~ msgbox s
	'~ else
	  '~ msgbox "Cannot open COM" & com_port.commport
	'~ end if
	
	'~ set com_port = nothing
'GMToffset = "d-8"
' msgbox GMToffset & " " & FormatDateTime&#40;now&#40;&#41;,0&#41;
' Windows command line/batch file&#58;
' echo d-8 %date% %time%      Windows command in batch file yields...
' column numbers. second set is relative to i
'         0000000001111111112222  
' 1234    0123456789012345678901	
' d-8 Fri 10/06/2006 20&#58;46&#58;15.32	 result of echo commmand, above. hr has leading space if < 10. 24 hr clock


'************************************************************
' ZBasic

function SetDateTime&#40;s as string&#41; as boolean
	dim i as byte, n as byte
	dim mm as byte, d as byte, y as integer
	dim h as byte, m as byte, secs as single
	
	i = 2 ' skip over the 1st char in line
	GMToffset = strInt&#40;mid&#40;s,i&#41;, n&#41;
	i = i + n + 1 ' skip over GMT offset, 1 or 2 digits
	' skip over dayname if present, and spaces
	do while &#40;not isNumeric&#40;asc&#40;s,i&#41;&#41;&#41;
		i = i + 1
	loop
	
	mm = cbyte&#40;strInt&#40;mid&#40;s,i,2&#41;, n&#41;&#41; ' 1 or 2 digits
	i = i + n + 1 ' skip the /
	d = cbyte&#40;strInt&#40;mid&#40;s,i,2&#41;, n&#41;&#41; ' 1 or 2 digits
	i = i + n + 1 ' skip the /	
	y = strInt&#40;mid&#40;s,i,4&#41;, n&#41; ' 4 digits
	i = i + n + 1
	
	i = i + skipSpace&#40;mid&#40;s, i&#41;&#41;
	' support either 12 or 24 hr format hh&#58;mm&#58;ss &#91;AMPM&#93;
	h = cbyte&#40;strInt&#40;mid&#40;s,i,2&#41;, n&#41;&#41; ' hours 1 or 2 digits
	i = i + n + 1  ' skip the &#58;
	m = cbyte&#40;strInt&#40;mid&#40;s,i,2&#41;, n&#41;&#41; ' minutes 1 or 2 digits
	i = i + n + 1  ' slip the &#58;
	call valueS&#40;mid&#40;s,i, 5&#41;, secs, SetDateTime&#41; ' seconds, may be a float

	if strCompare&#40;mid&#40;s, i&#41;, "PM", TRUE&#41; = 0 then
		h = h + 12
	end if
	if &#40;y < 100&#41; then
		y = y + 2000 ' y3K bug to come. I'll be gone!
	end if
	
	''' set date time in the VM
	call PutTimeStamp&#40;y, mm, d, h, m, secs&#41;
	debug.print "SetDateTime ";cstr&#40;GMToffset&#41;;" ";cstr&#40;mm&#41;;"/";cstr&#40;d&#41;;"/";cstr&#40;y&#41;;" ";cstr&#40;h&#41;;"&#58;";cstr&#40;m&#41;;"&#58;";cstr&#40;secs&#41;
end function	

'''''''''''''''''''''''''''''''''''''''''''''''''''''
Function IsNumeric&#40;ByVal b as Byte&#41; as Boolean
	IsNumeric = TRUE ' assume
	select case &#40;b&#41;
		case asc&#40;"0"&#41; TO asc&#40;"9"&#41;
		case asc&#40;"-"&#41;
		case asc&#40;"."&#41;
		case else
				IsNumeric = FALSE
	end select
	'''debug.print "IsNumeric '";chr&#40;b&#41;;"' ";cstr&#40;isNumeric&#41;
End Function

'''''''''''''''''''''''''''''''''''''''''''''''''''''
function skipSpace&#40;byval s as string&#41; as byte
	skipSpace  = 0
	do while &#40;asc&#40;s, skipSpace+1&#41; = asc&#40;" "&#41;&#41; ' strings' index begins with 1
		skipSpace = skipSpace + 1
	loop
	'''debug.print "skipSpace ";s;" ";cstr&#40;skipSpace&#41;
end function
'''''''''''''''''''''''''''''''''''''''''''''''''''''
function StrInt&#40;byval s1 as string, byref count as byte&#41; as integer
	dim n as byte
	dim ok as BOOLEAN
	dim v as single
	
	StrInt = 0
	count = 0
	' get number of digits in number
	for n = 0 to cbyte&#40;len&#40;s1&#41;&#41; - 1
		if not IsNumeric&#40;asc&#40;mid&#40;s1,n+1,1&#41;&#41;&#41; then
			exit for
		end if
	next
	count = n 

	if &#40;count > 0&#41; then
		' convert string number to float
		call valueS&#40;mid&#40;s1, 1, count&#41;, v, ok&#41;
		if &#40;ok&#41; then ' convert to integer
			StrInt = cint&#40;v&#41;
		end if
	end if
	'''debug.print "StrInt ";s1;" ";cstr&#40;strInt&#41;;" v=";cstr&#40;v&#41;;" count=";cstr&#40;count&#41;
end functionFirst, PC side code, then ZBasic code.


Attachments
ZBasic SetTime.zip
vbs code as shown
(444 Bytes) Downloaded 4648 times
stevech
Posts: 715
Joined: 22 February 2006, 20:56 PM

Post by stevech »

Oops. Bug fix due to insufficient programmer IQ:

In my ZBasic code, above, replace this

if strCompare(mid(s, i), "PM", TRUE) = 0 then

with this

if strFind(mid(s, i), "PM", i, TRUE) = 0 then
Post Reply