Hi Rick,
Poking around at wwUtils to see if I can use some of its functions related to string building and I've identified a bug in ShortTime. According to the docs the string returned should include am/pm but I've found it does not. If I change the RETURN value from RETURN LOWER(STUFF(lcTime,6,4,""))
to RETURN LOWER(STUFF(lcTime,6,1,""))
it does include the am/pm.
ACTIVATE SCREEN
CLEAR
test=DATETIME()
?test
? [include time with wwUtils ShortTime]
tlIncludeTime=.t.
?CMONTH(m.test)+[ ]+ALLTRIM(TRANSFORM(DAY(m.test)))+[, ]+ALLTRIM(TRANSFORM(YEAR(m.test)))+IIF(m.tlIncludeTime,[ ]+ShortTime(m.test),[])
? [include time with myShortTime]
tlIncludeTime=.t.
?CMONTH(m.test)+[ ]+ALLTRIM(TRANSFORM(DAY(m.test)))+[, ]+ALLTRIM(TRANSFORM(YEAR(m.test)))+IIF(m.tlIncludeTime,[ ]+MyShortTime(m.test),[])
? [don't include time]
tlIncludeTime=.f.
?CMONTH(m.test)+[ ]+ALLTRIM(TRANSFORM(DAY(m.test)))+[, ]+ALLTRIM(TRANSFORM(YEAR(m.test)))+IIF(m.tlIncludeTime,[ ]+MyShortTime(m.test),[])
************************************************************************
* ShortTime
****************************************
*** Function: Creates a short date string in the format of
*** 01:10pm
*** Assume:
*** Pass:
*** Return:
************************************************************************
FUNCTION MyShortTime(ltTime)
LOCAL lcTime
IF EMPTY(ltTime)
RETURN ""
ENDIF
lcTime = TTOC(ltTime,2)
*** Strip off seconds and space
RETURN LOWER(STUFF(lcTime,6,1,""))
ENDFUNC
* ShortTime

Not sure, but it works for me:
+++ Rick ---
And you've got RETURN LOWER(STUFF(lcTime,6,4,""))
as the return value in your wwutils.prg?
This is what I have:
************************************************************************
* ShortTime
****************************************
*** Function: Creates a short date string in the format of
*** 01:10pm
*** Assume:
*** Pass:
*** Return:
************************************************************************
FUNCTION ShortTime(ltTime)
LOCAL lcTime
IF EMPTY(ltTime)
RETURN ""
ENDIF
lcTime = TTOC(ltTime,2)
*** Strip off seconds and space
RETURN LOWER(STUFF(lcTime,6,4,""))
ENDFUNC
* ShortTime
I guess I'm not sure what you're on about since the following works correctly AFAIK:
lcTime = TTOC(DATETIME(),2)
? lcTime
*** 08:14:44 pm
*** Skip to 6th char fill 4 with blanks (remove 4)
? LOWER(STUFF(lcTime,6,4,"")
*** 08:14pm
Hmmm... I guess the SET DATE TO
setting will affect this. The above works with SET DATE TO AMERICAN
or any of the other locale specifiers (which oddly enough return am/pm times). However, it looks like SET DATE TO LONG
or SET DATE TO SHORT
will strip the leading 0's and that will cause the date to break - I think that's what you're seeing.
Looks like the SET DATE
needs to be explicitly set and reset.
+++ Rick ---

Thanks. I was just testing COMPATIBLE and ANSI but hadn't thought of DATE. I believe we use MDY or DMY in our app environment. I suspect that behaves in the same manner as LONG/SHORT. Will give that a go to verify.
There must be some other setting involved here.
ACTIVATE SCREEN
CLEAR
? [test date value]
testDate=DATETIME()
? [date mdy]
SET DATE MDY
?testdate
?LOWER(STUFF(TTOC(testDate,2),6,4,""))
?LOWER(STUFF(TTOC(testDate,2),6,3,""))
?LOWER(STUFF(TTOC(testDate,2),6,2,""))
?LOWER(STUFF(TTOC(testDate,2),6,1,""))
? [date dmy]
SET DATE DMY
?testdate
?LOWER(STUFF(TTOC(testDate,2),6,4,""))
?LOWER(STUFF(TTOC(testDate,2),6,3,""))
?LOWER(STUFF(TTOC(testDate,2),6,2,""))
?LOWER(STUFF(TTOC(testDate,2),6,1,""))
? [date american]
SET DATE AMERICAN
?testdate
?LOWER(STUFF(TTOC(testDate,2),6,4,""))
?LOWER(STUFF(TTOC(testDate,2),6,3,""))
?LOWER(STUFF(TTOC(testDate,2),6,2,""))
?LOWER(STUFF(TTOC(testDate,2),6,1,""))
? [date british]
SET DATE BRITISH
?testdate
?LOWER(STUFF(TTOC(testDate,2),6,4,""))
?LOWER(STUFF(TTOC(testDate,2),6,3,""))
?LOWER(STUFF(TTOC(testDate,2),6,2,""))
?LOWER(STUFF(TTOC(testDate,2),6,1,""))
? [date ansi]
SET DATE ANSI
?testdate
?LOWER(STUFF(TTOC(testDate,2),6,4,""))
?LOWER(STUFF(TTOC(testDate,2),6,3,""))
?LOWER(STUFF(TTOC(testDate,2),6,2,""))
?LOWER(STUFF(TTOC(testDate,2),6,1,""))
SET DATE MDY
gives me this:
I'll keep poking at this as time permits.
You should print out the value of TTOC()
- that's the key that the string translation is made off of.
TTOC() behaves differently than normal formatted date strings.
+++ Rick ---
Rejiggered this to do as you suggested and dumped the results to a file. I'm still seeing the desired formatting only when using ,1 for the STUFF.
**************************************
* Program: timeparsingtests.prg
* Date: 09/26/2023 10:32 AM
* VFP Version: Visual FoxPro 09.00.0000.7423 for Windows
* Notes:
**************************************
ACTIVATE SCREEN
CLEAR
testDate=DATETIME()
SET DATE MDY
TEXT TO lcResults TEXTMERGE NOSHOW FLAGS 1 PRETEXT 1+2
date is MDY
testdate is <<TRANSFORM(testdate)>>
TTOC(testdate,2) is <<TTOC(testdate,2)>>
LOWER(STUFF(TTOC(testDate,2),6,4,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,4,""))>>
LOWER(STUFF(TTOC(testDate,2),6,3,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,3,""))>>
LOWER(STUFF(TTOC(testDate,2),6,2,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,2,""))>>
LOWER(STUFF(TTOC(testDate,2),6,1,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,1,""))>>
ENDTEXT
SET DATE DMY
TEXT TO lcResults ADDITIVE TEXTMERGE NOSHOW FLAGS 1 PRETEXT 1+2
date is DmY
testdate is <<TRANSFORM(testdate)>>
TTOC(testdate,2) is <<TTOC(testdate,2)>>
LOWER(STUFF(TTOC(testDate,2),6,4,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,4,""))>>
LOWER(STUFF(TTOC(testDate,2),6,3,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,3,""))>>
LOWER(STUFF(TTOC(testDate,2),6,2,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,2,""))>>
LOWER(STUFF(TTOC(testDate,2),6,1,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,1,""))>>
ENDTEXT
SET DATE AMERICAN
TEXT TO lcResults ADDITIVE TEXTMERGE NOSHOW FLAGS 1 PRETEXT 1+2
date is AMERICAN
testdate is <<TRANSFORM(testdate)>>
TTOC(testdate,2) is <<TTOC(testdate,2)>>
LOWER(STUFF(TTOC(testDate,2),6,4,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,4,""))>>
LOWER(STUFF(TTOC(testDate,2),6,3,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,3,""))>>
LOWER(STUFF(TTOC(testDate,2),6,2,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,2,""))>>
LOWER(STUFF(TTOC(testDate,2),6,1,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,1,""))>>
ENDTEXT
SET DATE BRITISH
TEXT TO lcResults ADDITIVE TEXTMERGE NOSHOW FLAGS 1 PRETEXT 1+2
date is BRITISH
testdate is <<TRANSFORM(testdate)>>
TTOC(testdate,2) is <<TTOC(testdate,2)>>
LOWER(STUFF(TTOC(testDate,2),6,4,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,4,""))>>
LOWER(STUFF(TTOC(testDate,2),6,3,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,3,""))>>
LOWER(STUFF(TTOC(testDate,2),6,2,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,2,""))>>
LOWER(STUFF(TTOC(testDate,2),6,1,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,1,""))>>
date ansi
ENDTEXT
SET DATE ANSI
TEXT TO lcResults ADDITIVE TEXTMERGE NOSHOW FLAGS 1 PRETEXT 1+2
date is ANSI
testdate is <<TRANSFORM(testdate)>>
TTOC(testdate,2) is <<TTOC(testdate,2)>>
LOWER(STUFF(TTOC(testDate,2),6,4,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,4,""))>>
LOWER(STUFF(TTOC(testDate,2),6,3,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,3,""))>>
LOWER(STUFF(TTOC(testDate,2),6,2,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,2,""))>>
LOWER(STUFF(TTOC(testDate,2),6,1,"")) is <<LOWER(STUFF(TTOC(testDate,2),6,1,""))>>
ENDTEXT
STRTOFILE(m.lcResults,[timeparsing.txt],0)
MODIFY FILE timeparsing.txt NOWAIT
SET DATE MDY
Here are the results:
date is MDY
testdate is 09/26/2023 03:27 PM
TTOC(testdate,2) is 03:27 PM
LOWER(STUFF(TTOC(testDate,2),6,4,"")) is 03:27
LOWER(STUFF(TTOC(testDate,2),6,3,"")) is 03:27
LOWER(STUFF(TTOC(testDate,2),6,2,"")) is 03:27m
LOWER(STUFF(TTOC(testDate,2),6,1,"")) is 03:27pm
date is DMY
testdate is 26/09/2023 03:27 PM
TTOC(testdate,2) is 03:27 PM
LOWER(STUFF(TTOC(testDate,2),6,4,"")) is 03:27
LOWER(STUFF(TTOC(testDate,2),6,3,"")) is 03:27
LOWER(STUFF(TTOC(testDate,2),6,2,"")) is 03:27m
LOWER(STUFF(TTOC(testDate,2),6,1,"")) is 03:27pm
date is AMERICAN
testdate is 09/26/2023 03:27 PM
TTOC(testdate,2) is 03:27 PM
LOWER(STUFF(TTOC(testDate,2),6,4,"")) is 03:27
LOWER(STUFF(TTOC(testDate,2),6,3,"")) is 03:27
LOWER(STUFF(TTOC(testDate,2),6,2,"")) is 03:27m
LOWER(STUFF(TTOC(testDate,2),6,1,"")) is 03:27pm
date is BRITISH
testdate is 26/09/2023 03:27 PM
TTOC(testdate,2) is 03:27 PM
LOWER(STUFF(TTOC(testDate,2),6,4,"")) is 03:27
LOWER(STUFF(TTOC(testDate,2),6,3,"")) is 03:27
LOWER(STUFF(TTOC(testDate,2),6,2,"")) is 03:27m
LOWER(STUFF(TTOC(testDate,2),6,1,"")) is 03:27pm
date ansi
date is ANSI
testdate is 2023.09.26 03:27 PM
TTOC(testdate,2) is 03:27 PM
LOWER(STUFF(TTOC(testDate,2),6,4,"")) is 03:27
LOWER(STUFF(TTOC(testDate,2),6,3,"")) is 03:27
LOWER(STUFF(TTOC(testDate,2),6,2,"")) is 03:27m
LOWER(STUFF(TTOC(testDate,2),6,1,"")) is 03:27pm
I also tried messing with ANSI, CENTRY and COMPATIBLE.
I'm not sure why STUFF()
would behave differently for you or me. I get TTOC()
may produce different results, but based on this run it's the same through all of those instances. The only thing that changes TTOC()
seems to be SET DATE TO LONG/SHORT.
I'm not sure why STUFF() would behave differently.
The result I get from your code is:
date is MDY
testdate is 09/26/2023 01:03:34 PM
TTOC(testdate,2) is 01:03:34 PM
LOWER(STUFF(TTOC(testDate,2),6,4,"")) is 01:03pm
LOWER(STUFF(TTOC(testDate,2),6,3,"")) is 01:03 pm
LOWER(STUFF(TTOC(testDate,2),6,2,"")) is 01:034 pm
LOWER(STUFF(TTOC(testDate,2),6,1,"")) is 01:0334 pm
date is DmY
testdate is 26/09/2023 01:03:34 PM
TTOC(testdate,2) is 01:03:34 PM
LOWER(STUFF(TTOC(testDate,2),6,4,"")) is 01:03pm
LOWER(STUFF(TTOC(testDate,2),6,3,"")) is 01:03 pm
LOWER(STUFF(TTOC(testDate,2),6,2,"")) is 01:034 pm
LOWER(STUFF(TTOC(testDate,2),6,1,"")) is 01:0334 pm
date is AMERICAN
testdate is 09/26/2023 01:03:34 PM
TTOC(testdate,2) is 01:03:34 PM
LOWER(STUFF(TTOC(testDate,2),6,4,"")) is 01:03pm
LOWER(STUFF(TTOC(testDate,2),6,3,"")) is 01:03 pm
LOWER(STUFF(TTOC(testDate,2),6,2,"")) is 01:034 pm
LOWER(STUFF(TTOC(testDate,2),6,1,"")) is 01:0334 pm
date is BRITISH
testdate is 26/09/2023 01:03:34 PM
TTOC(testdate,2) is 01:03:34 PM
LOWER(STUFF(TTOC(testDate,2),6,4,"")) is 01:03pm
LOWER(STUFF(TTOC(testDate,2),6,3,"")) is 01:03 pm
LOWER(STUFF(TTOC(testDate,2),6,2,"")) is 01:034 pm
LOWER(STUFF(TTOC(testDate,2),6,1,"")) is 01:0334 pm
date ansi
date is ANSI
testdate is 2023.09.26 01:03:34 PM
TTOC(testdate,2) is 01:03:34 PM
LOWER(STUFF(TTOC(testDate,2),6,4,"")) is 01:03pm
LOWER(STUFF(TTOC(testDate,2),6,3,"")) is 01:03 pm
LOWER(STUFF(TTOC(testDate,2),6,2,"")) is 01:034 pm
LOWER(STUFF(TTOC(testDate,2),6,1,"")) is 01:0334 pm
+++ Rick ---
Me, either. Must be some other arcane VFP setting affecting this. Looking at HOUR and SECONDS now...
Got it, I think. What is your setting for SET SECONDS?
And just so that there's no suspense here, it's OFF on my system. If I set it on, STUFF with 4 behaves as on your system.
Yup that would make sense. I'm the 4
is stripping of the :00
and if there are no seconds that will strip off everything and not capture the AM/PM
.
So looks like:
The method has to capture SET DATE TO AMERICAN
and SET SECONDS OFF
then account for the missing seconds (no need to gen and then strip them with TTOC()
).
************************************************************************
* ShortTime
****************************************
*** Function: Creates a short date string in the format of
*** 01:10pm
*** Assume: US Time Format
*** Pass: Date and Time value
*** Return: string
************************************************************************
FUNCTION ShortTime(ltTime)
LOCAL lcTime, lcDate, lcSeconds
IF EMPTY(ltTime)
RETURN ""
ENDIF
lcSeconds = SET("SECONDS")
lcDate = SET("DATE")
SET SECONDS OFF
SET DATE TO AMERICAN
lcTime = TTOC(ltTime,2)
SET SECONDS &lcSeconds
SET DATE TO &lcDate
*** Strip off seconds and space
RETURN LOWER(STUFF(lcTime,6,1,""))
ENDFUNC
* ShortTime
To test you can try this with different SET DATE
and SET SECONDS
values...
DO wwUtils
SET DATE TO LONG
SET SECONDS ON
? DATETIME()
? TTOC(DATETIME())
? ShortTime(DATETIME())
? SET("DATE")
? SET("SECONDS")
+++ Rick ---
I was going a bit more minimalist with my refactor but I also wasn't concerned about SHORT or LONG.
FUNCTION ShortTime(ltTime)
LOCAL lcTime, lcSeconds, lcReturn
IF EMPTY(ltTime)
RETURN ""
ENDIF
lcSeconds=SET("Seconds")
SET SECONDS ON
lcTime = TTOC(ltTime,2)
*** Strip off seconds and space
lcReturn=LOWER(STUFF(lcTime,6,4,""))
SET SECONDS &lcSeconds
*!* - rk - 2023-9-22 - my temp fix for making sure am/pm is included
RETURN lcReturn
Capturing the region doesn't matter with the exception of LONG/SHORT and this works fine for me. But I'll go with your refactor since mine does not handle LONG/SHORT. I will test out all the variations and if I run across one that doesn't work as expected I'll let you know.