VFP 学习、开发漫谈 (三)
今天,就从一个古老的 DATE()函数聊起吧。DATE()函数的主要功能是返回系统时钟的当前日期,如:?DATE() 的运行结果是 2014.02.24。显示的格式受 Set Date和 Set Century设置的影响。我们中国人习惯于“年月日”格式,一般设置 Set Date Ansi,为了避免2000年问题,设置 Set Century ON 以便用4位数表示年份。
DATE()函数还有一个附属功能:返回指定年、月、日的日期,如:DATE(2014,2,24)将返回 2014.02.24。这里要注意一点:由年月日三个数值组成的日期必须是一个有效的日期,如 ? DATE(2014,13,24) 在运行时就出现语法错误,因为月份不可能有13月。这一点就没有 CTOD()函数健壮,? CTOD('2014.13.24') 返回空日期。
我们可以利用CTOD()函数对无效字符串返回空日期的特点,轻松判断某一年是闰年还是平年。思路就是判断该年度的2月29日是否是一个有效的日期。下述代码可判断2014年是闰年还是平年:
? IIF(EMPTY(CTOD('2014.2.29')),'2014年是平年','2014年是闰年')
这要比闰年的判断依据“能被4整除不能被100整除或能被400整除……”要简单的多!
给一个变量赋一个空日期常数:dNow = {},给一个变量赋一个特定的值:dNow = {^2014.2.24},注意年份前的“^”。有些书上,对常数和常量混为一谈,常数是一个字面量,如:1,"China",.T.,{^2012.02.24},常量是指用 #DEFINE 定义的符号,如:#DEFINE CR CHR(13)。
在实际编程中,我们经常碰到需要取某月的最后一天,如:查询材料明细帐时,需要输入日期范围,若当前日期大于10号,一般查询本月业务较多,默认日期范围设置为本月1日到当前日期是合适的;若当前日期小于10号,则查询上月业务较多,默认日期范围设为上月1日至上月月末较合适。类似的应用还有很多。
若要取上个月最后一天可采用:DATE()-DAY(DATE()),其思路是将当前日期前移若干天数。若要取变量 dDate的月份最后一天,可采用:GOMONTH(dDate,1)-DAY(GOMONTH(dDate,1)),思路是将日期后移一个月然后再前移若干天。
我们都知道 DTOS(dDate) 返回 YYYYMMDD 的字符串,如:20140224。那么如何将 YYYYMMDD 字符串转换为日期型变量呢?
第一种方法:将源字符串中的年、月、日分离出来,加上分隔符“.”后再使用 CTOD()转换成日期型变量。这是最先想到的方法。
? CTOD(LEFT(cDate,4) + '.' + SUBSTR(cDate,3,2) + '.' + RIGH(cDate,2))
第二种方法:将源字符串中的年、月、日分离出来转换成数值型,再使用 DATE()函数返回一个日期型变量。这种方法也不太简练。
? DATE(VAL(LEFT(cDate,4)),VAL(SUBSTR(cDate,3,2)),VAL(RIGH(cDate,2)))
第三种方法:使用TRANSFORM()函数,将源字符串转换成“YYYY.MM.DD”格式,再使用 CTOD()函数。这种方法最简练。
? CTOD(TRANS(cDate,'@R 9999.99.99'))
说起 TRANSFORM()函数,我真是爱死它啦!再举几个应用实例:
1. 将日期变量 dDate 显示成“2014年2月24日”字样
? TRANS(dDate,'@YL') && @YL 表示长日期格式,限于中文操作系统
2. 对于一个数值型变量 nNum,将其转换成字符串,没有前导空格和小数点后面的 0,如:123.00 转换成 123
? TRANS(nNum)
3. 若不知道变量 uVal 的数据类型,现在要将其转换成字符串,最简单的方法还是使用 TRANS()函数。
? "uVal=" + TRANS(uVal)
4. 将一个整型变量 nNum 转换成长度为 6 位的字符串,左边用 0 填充,如:123 转换为 000123。
? TRANS(nNum,'@L 999999')
实际应用中,我也经常使用 PADL()函数,如下:
? PADL(nNum,6,'0')
5. 变量 cMac 存储的值为网卡的 MAC 地址,如:002421DD0303,现在要将其显示为 00-24-21-DD-03-03
? TRANS(cMac,'@R XX-XX-XX-XX-XX-XX')
DATE()函数提取的是本地终端上的当前日期。实际应用中,因CMOS电池失效造成系统时钟错误的情况经常遇到。此时,DATE()函数返回的是错误的日期。对于不太重要的日期或只对日期赋初值,而用户还可以二次编辑时,可以使用 Date()函数,问题不大。对于重要的日期,必须另辟蹊径。解决的思路是将终端的日期与服务器上的日期同步或干脆直接取服务器日期。
假设服务器的 IP 是 192.168.0.1,在 VFP 下运行“RUN Net Time \\192.168.0.1 /Set /Yes”即可将本地终端的时间与服务器同步。
直接取服务器的当前日期,需要借助 SQL Server,最好是定义一个取当前日期的自定义函数 GetDate(),如下所示(其中的 GetHandle()是建立一个连接到SQL Server的连接句柄并保存到全局变量 gnHandle):
程序代码:
FUNCTION GetDate() LOCAL nSelect,dDate nSelect = SELECT() IF GetHandle()<0 OR SQLEXEC(gnHandle,'SELECT getdate()','curRet')<0 dDate = DATE() && 取服务器时间失败时,取本机时间 ELSE dDate = TTOD(curRet.exp) && 由日期时间型转换为日期型 USE IN curRet ENDIF SELECT (nSelect) RETURN dDate ENDFUNC FUNCTION GetHandle() * 检测连接状态 LOCAL nSqlState IF TYPE('gnHandle') = 'U' PUBLIC gnHandle ENDIF TRY nSqlState = SQLEXEC(gnHandle,"") CATCH nSqlState = -1 ENDTRY * 连接无效时,重建连接 IF nSqlState < 1 gnHandle = SQLSTRINGCONNECT("DRIVER=SQL Server;SERVER=192.168.0.1;UID=sa;PWD=12345;DATABASE=mis") ENDIF * 重建连接失败时给出提示 IF gnHandle < 0 MESSAGEBOX('与 SQL Server 数据库连接失败!',16,'提示') ENDIF * 返回连接句柄 RETURN gnHandle ENDFUNC
[ 本帖最后由 liuxingang28 于 2014-7-3 09:18 编辑 ]