Welcome To The Home Of The Visual FoxPro Experts  
home. signup. forum. archives. search. google. articles. downloads. faq. members. weblogs. file info. rss.
 From: Cetin Basoz
  Where is Cetin Basoz?
 Cetin Basoz
 To: Shaheryar Rashed
  Where is Shaheryar Rashed?
 Shaheryar Rashed
Subject: RE: time totals
Thread ID: 395497 Message ID: 395712 # Views: 44 # Ratings: 4
Version: Visual FoxPro 9 SP2 Category: Forms
Date: Friday, January 17, 2014 1:24:20 PM         

> Sir Cetin!
> superb solution. 1 more request, i want to learn more about ctot() function for that in future i fully approach about how to multiply, devide and any other formula myself. guide me where i can find ctot() and ttoc() function's details. bcz vfp help dont contain (as i searched) too much information about these functions
> Regards, and many many thanks to help

I don't know what can I add to help says. I will try anyway.

ctot() converts values that looks like a date, datetime or time to a datetime value. Saying "looks like" I mean even '0', '1p' ... works. It is not perfect in that understanding "now", "today" ... also as datetime values as in some other languages but we can live with that. Maybe the only trick you need to know about that (and seems to be undocumented) if you give it '0' as the value it returns '1899/12/30 12:00:00 AM'. Or give it '1' and it would return 1899/12/30 01:00:00.

When you store just the time portion like '8:30 AM', '9p', '10:40' etc, in 24 hrs format these would resolve to:
1899/12/30 08:30:00
1899/12/30 21:00:00
1899/12/30 10:40:00

and that serves very well for doing date math. We don't care the date portion is in 1899. The other operand too would have the same date anyway.

ctot('8:30 PM') - ctot('0')


datetime(1899,12,30,20,30,0) - datetime(1899,12,30,0,0,0)

which simply would give us the seconds since midnight. So I can say that ctot() works well for calculations where only time is saved as character.

The other thing I see worth to mention is if you are using CTOT() with a date for conversion then be sure that date is expressed date format free. What I mean is, do not try to convert a value like:


It is peculiar if it is January 2nd or February 1st. You can use this when you are doing ttoc(), ctot() both in the same routine. Then the date format would be the same for both removing the ambiguity. Or you may use it when you are 100% sure of the format and have the same format set when it executes (say SET DATE DMY and I could then surely say that it is Feb 1st).

Other than that if you would store a date/datetime (with date portion) be sure that you are storing date portion in YYYY/MM/DD format (with or without separators). For example:

if I store the value as 20000102 without separators (know your domain, you are aware of what you store in the first place), then I could transform this to 2000/01/02:

lcMyDate = Transform('20000102', '@R 9999/99/99')

Now that we have something like:
at hand, all we need to convert this to date or datetime (ctod and ctot, ctod works the same way) is to add a '^' in front to tell VFP "no matter what the date formats are I am giving you strictly in YYYY/MM/DD format, please create a date -ctod- or datetime -ctot- value for me". And you get the correct Jan 2nd, 2000.

lcMyDate = Transform('20000102', '@R 9999/99/99')
ltMyDateTime = Ctot('^'+m.lcmydate)
? m.ltmydatetime

ltMyDate = Ctod('^'+m.lcmydate) && if there were time in string ctod() would drop that and still return a correct date
? m.ltmydate

So to recap for ctot() as they are used often in any scheduling datetime math:

1) If you use ctot('0') it returns midnight (don't care the date part).

2)Something like ctot('8:30') returns 8:30 AM whether the hours is set to 12 or 24. ctot('1p'), ctot('1:00pm'), ctot('1:00 PM'), ctot('13:00'),ctot('13') all return the same 1 PM (again date part doesn't matter, it is fixed at 1899/12/30).

Using these 2 rules, we can convert any time stored as a character value to seconds since midnight:

lnSecondsSinceMidnight = ctot( m.lcTime ) - ctot( '0' )

BTW this works because any time only value is within 24 hours so having a fixed date portion is just fine.

Now to ttoc(). There isn't much to tell about that. Honestly the only things I find useful about TTOC() are:

1) TTOC( m.ltDateTime, 1 ) to convert the value into a string that is strictly in yyyyMMddhhmmss format.
2) TTOC( m.ltDateTime, 2 ) to create elapsed time in string format WHEN the elapsed time is within 24 hours + hours is set to 24.

I don't use TTOC( m.ltDateTime, 3 ) just because it was introduced later, I can do that with some transformation myself where needed.
I don't use TTOC( m.ltDateTime ) - without second parameter - unless maybe I am using TTOC() and CTOT() within same routine (Convert back and forth in same routine where date formats are exactly the same for both - no set date in between).

The only thing worth sampling is ttoc( , 1 ) I think.

lcMyTime = ttoc( DateTime( 2000, 2, 29, 13, 0, 0 ), 1 ) && 20000229130000 

* I can use this value say as a backup file's name 
* consider in fact we are using just datetime() above
lcBackup = forcepath( forceext( m.lcMyTime, 'bak' ), 'c:\MyBackups' ) && c:\MyBackups\20000229130000.bak

* later in time I can convert either lcMyTime or lcBackup to a valid datetime value
* say we did something like adir and have lcFileName = 'c:\MyBackups\20000229130000.bak'
* lcMyTime = JustStem( m.lcFileName )
* this is a one liner, using more just to be explicit

lcDateTime = transform( m.lcMyTime, '@R 9999/99/99 99:99:99' )
ltMyTime   = ctot( '^' + m.lcDateTime )
? m.ltMyTime

There is no ambiguity, I get exactly what I meant to store no matter what the current date and hour formats are.

2) This one of using ,2 as I said work only within 24 hours elapsed times and when hours is set to 24. In that case this is a sample way to format elapsed times as string (say a schedule report):

* remember hours is set to 24
? ttoc( ctot('3pm') - ( Ctot('1am') - ctot('0') ) ) && 14:00:00 as a character value

Of course, if you are dealing with schedule systems, then you should have a method that gets the two values and returns the string instead of this trick. Your method then would check the values if they are character or datetime and may also handle times that span days then return a custom string like .Net's:


using possibly textmerge().

And one final tip, if this is really a tip then it is an important tip I will mark it bold here :)

TIP: Instead of ctot() and ttoc() and ctod() and ttod() you can use cast() if your version supports that. Why would you do that?

TToD() doesn't accept a date as its first parameter and errors out, same goes with DToT() where it doesn't accept a datetime value as first parameter. But wouldn't that be odd not to be able to convert a date to a date or a datetime to datetime :)

Instead we can use Cast() for all those TToC(), TToD(), DToT(), DToD(), CToD(), CToT() and this not only give us a uniform call for a function series, it also make it possible to use this directly in an SQL command WHERE we execute that command against another backend (like MS SQL server). "Two birds with a stone" case :) TToC(), TToD(), DToT(), DToD(), CToD(), CToT() are specific to VFP where CAST() is not.

? Cast( Date() as date )
? Cast( DateTime() as date )
? Cast( '^2000/2/29 10:40' as date )

? Cast( Date() as datetime )
? Cast( DateTime() as datetime )
? Cast( '^2000/2/29 10:40' as datetime )

Just tell what you want :)


Cetin Basoz

Give some sample data in code for your question - here is the tool you need to generate the code

My Blog

MongoDb Certified Developer
MongoDb Certified DBA

Support Wikipedia


time totals Posted by Shaheryar Rashed @ 1/15/2014 1:58:56 PM
RE: time totals Posted by David Mustakim @ 1/15/2014 2:18:45 PM
RE: time totals Posted by Shaheryar Rashed @ 1/15/2014 2:30:23 PM
RE: time totals Posted by David Mustakim @ 1/15/2014 2:47:42 PM
RE: time totals Posted by Shaheryar Rashed @ 1/15/2014 3:13:41 PM
RE: time totals Posted by Tore Bleken @ 1/15/2014 3:22:29 PM
RE: time totals Posted by Shaheryar Rashed @ 1/16/2014 7:36:37 AM
RE: time totals Posted by Anders Altberg @ 1/15/2014 4:51:39 PM
RE: time totals Posted by Cetin Basoz @ 1/15/2014 5:51:36 PM
RE: time totals Posted by Shaheryar Rashed @ 1/17/2014 6:51:16 AM
RE: time totals Posted by Cetin Basoz @ 1/17/2014 1:24:20 PM
RE: time totals Posted by Shaheryar Rashed @ 1/18/2014 6:45:09 AM
RE: time totals Posted by Anders Altberg @ 1/18/2014 11:50:19 PM