Web Connection
wwUtils ShortTime
Gravatar is a globally recognized avatar based on your email address. wwUtils ShortTime
  Richard Kaye
  All
  Sep 22, 2023 @ 08:20am

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
Gravatar is a globally recognized avatar based on your email address. re: wwUtils ShortTime
  Rick Strahl
  Richard Kaye
  Sep 22, 2023 @ 10:42am

Not sure, but it works for me:

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: wwUtils ShortTime
  Richard Kaye
  Rick Strahl
  Sep 22, 2023 @ 10:52am

And you've got RETURN LOWER(STUFF(lcTime,6,4,"")) as the return value in your wwutils.prg?

Gravatar is a globally recognized avatar based on your email address. re: wwUtils ShortTime
  Rick Strahl
  Richard Kaye
  Sep 23, 2023 @ 10:38am

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 ---

Gravatar is a globally recognized avatar based on your email address. re: wwUtils ShortTime
  Richard Kaye
  Rick Strahl
  Sep 26, 2023 @ 04:24am

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.

Gravatar is a globally recognized avatar based on your email address. re: wwUtils ShortTime
  Richard Kaye
  Rick Strahl
  Sep 26, 2023 @ 04:42am

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.

Gravatar is a globally recognized avatar based on your email address. re: wwUtils ShortTime
  Rick Strahl
  Richard Kaye
  Sep 26, 2023 @ 08:23am

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 ---

Gravatar is a globally recognized avatar based on your email address. re: wwUtils ShortTime
  Richard Kaye
  Rick Strahl
  Sep 26, 2023 @ 09:36am

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.

Gravatar is a globally recognized avatar based on your email address. re: wwUtils ShortTime
  Rick Strahl
  Richard Kaye
  Sep 26, 2023 @ 10:03am

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 ---

Gravatar is a globally recognized avatar based on your email address. re: wwUtils ShortTime
  Richard Kaye
  Rick Strahl
  Sep 26, 2023 @ 10:24am

Me, either. Must be some other arcane VFP setting affecting this. Looking at HOUR and SECONDS now...

Gravatar is a globally recognized avatar based on your email address. re: wwUtils ShortTime
  Richard Kaye
  Rick Strahl
  Sep 26, 2023 @ 10:25am

Got it, I think. What is your setting for SET SECONDS?

Gravatar is a globally recognized avatar based on your email address. re: wwUtils ShortTime
  Richard Kaye
  Rick Strahl
  Sep 26, 2023 @ 10:27am

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.

Gravatar is a globally recognized avatar based on your email address. re: wwUtils ShortTime
  Rick Strahl
  Richard Kaye
  Sep 26, 2023 @ 10:46am

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 ---

Gravatar is a globally recognized avatar based on your email address. re: wwUtils ShortTime
  Richard Kaye
  Rick Strahl
  Sep 26, 2023 @ 11:33am

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.

Gravatar is a globally recognized avatar based on your email address. re: wwUtils ShortTime
  Richard Kaye
  Richard Kaye
  Sep 26, 2023 @ 11:42am

All good. I've updated my local copy and assume you will have this in your next maintenance release.

© 1996-2025