标题:请教下各位大大:有没有体育项目秒表时间的加减算法?
只看楼主
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:1 
回复 30楼 shonken
校对了一下好象有点问题
试试:
? x_秒表加减('2022-07-09T23:59:08.999', '+11:1.124')  && 输出 2022-07-10T01:49:10.123
或简化点:
? x_秒表加减('2022-07-09T23:59:00', '+1:00')  && 输出 2022-07-10T00:09:00.000
2022-07-09 14:33
shonken
Rank: 2
等 级:论坛游民
帖 子:95
专家分:21
注 册:2017-1-15
得分:0 
谢谢校对
    LnSs = ArTime2[1] * 3600 + ArTime2[2] * 60 + ArTime2[3]
这句60,写成600

以下是引用吹水佬在2022-7-9 14:33:27的发言:

校对了一下好象有点问题
试试:
? x_秒表加减('2022-07-09T23:59:08.999', '+11:1.124')  && 输出 2022-07-10T01:49:10.123
或简化点:
? x_秒表加减('2022-07-09T23:59:00', '+1:00')  && 输出 2022-07-10T00:09:00.000

2022-07-09 15:06
mywisdom88
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:190
帖 子:3125
专家分:8340
注 册:2015-3-25
得分:2 
土方法,硬拼

CLEAR
c当前 = "32:20:9.419"
c加减 = "-1:8.412"
?c当前
?c加减
?秒表(c当前,c加减)

FUNCTION 秒表(c当前成绩,c加减成绩)
LOCAL c加减,c变动成绩
c当前成绩 = 标准格式(c当前成绩)

IF  OCCURS(".",c加减成绩) > 1
    MESSAGEBOX("加减成绩格式错误,最少包含2个“.”以上!",48,"提示")
    RETURN c当前成绩
ELSE
  
   c加减 = SUBSTR(c加减成绩,1,1)
   
   IF c加减 = "-" && 第一个字符是 -
      c变动成绩 = SUBSTR(c加减成绩,2)
      c变动成绩 = 标准格式(c变动成绩)
      RETURN 减少加时间(c当前成绩,c变动成绩)
   ELSE
      IF INLIST(c加减 , "+" ,":") && 第一个字符是 +或者:
         c变动成绩 = SUBSTR(c加减成绩,2)
      ELSE
         c变动成绩 = c加减成绩
      ENDIF
      c变动成绩 = 标准格式(c变动成绩)
      RETURN 增加时间(c当前成绩,c变动成绩)
   ENDIF
ENDIF   

ENDFUNC

FUNCTION 标准格式(HMSX)
*!* 标准格式 HH:MM:SS.SSS 格式
LOCAL FH,HH,MM,SS,SSS
IF INLIST(SUBSTR(HMSX,1,1),"+","-")
   FH = SUBSTR(HMSX,1,1)
   HMSX = SUBSTR(HMSX,2)
ELSE
   FH = ""
ENDIF      
*!* 取HHMMSS.SSS的.后面的前面3位   
SSS = PADL(SUBSTR(IIF(RAT(".",HMSX)>0,SUBSTR(HMSX,RAT(".",HMSX)+1),"000"),1,3),3,"0")

*!* 分别取HHMMSS中的SS,MM,HH
HMS = IIF(RAT(".",HMSX)=0,HMSX,SUBSTR(HMSX,1,RAT(".",HMSX)-1))
SS = PADL(SUBSTR(IIF(RAT(":",HMS)>0,SUBSTR(HMS,RAT(":",HMS)+1),HMS),1,2),2,"0")
HM = IIF(RAT(":",HMS)=0,"00",SUBSTR(HMS,1,RAT(":",HMS)-1))
MM = PADL(SUBSTR(IIF(RAT(":",HM)>0,SUBSTR(HM,RAT(":",HM)+1),HM),1,2),2,"0")
HH = PADL(SUBSTR(IIF(RAT(":",HM)=0,"00",SUBSTR(HM,1,RAT(":",HM)-1)),1,2),2,"0")

RETURN FH + HH + ":" + MM + ":" + SS + "." + SSS
ENDFUNC

FUNCTION 增加时间(c当前成绩,c变动成绩)
LOCAL HH,HH1,HH2,MM,MM1,MM2,SS,SS1,SS2,SSS,SSS1,SS2
HH1 = INT(VAL(SUBSTR(c当前成绩,1,2)))
MM1 = INT(VAL(SUBSTR(c当前成绩,4,2)))
SS1 = INT(VAL(SUBSTR(c当前成绩,7,2)))
SSS1 = INT(VAL(SUBSTR(c当前成绩,10,3)))

HH2 = INT(VAL(SUBSTR(c变动成绩,1,2)))
MM2 = INT(VAL(SUBSTR(c变动成绩,4,2)))
SS2 = INT(VAL(SUBSTR(c变动成绩,7,2)))
SSS2 = INT(VAL(SUBSTR(c变动成绩,10,3)))

SSS = SSS1 + SSS2
IF SSS >= 1000
   SSS = SSS - 1000
   SS1 = SS1 + 1
ENDIF
SS = SS1 + SS2
IF SS>=60
   SS = SS - 60
   MM1 = MM1 + 1
ENDIF
MM = MM1 + MM2
IF MM>=60
   MM = MM - 60
   HH1 = HH1 + 1
ENDIF   
HH = HH1 + HH2

RETURN PADL(HH,2,"0") + ":" + PADL(MM,2,"0") + ":" + PADL(SS,2,"0") + "." + PADL(SSS,3,"0")
ENDFUNC

FUNCTION 减少加时间(c当前成绩,c变动成绩)
LOCAL HH,HH1,HH2,MM,MM1,MM2,SS,SS1,SS2,SSS,SSS1,SS2
HH1 = INT(VAL(SUBSTR(c当前成绩,1,2)))
MM1 = INT(VAL(SUBSTR(c当前成绩,4,2)))
SS1 = INT(VAL(SUBSTR(c当前成绩,7,2)))
SSS1 = INT(VAL(SUBSTR(c当前成绩,10,3)))

HH2 = INT(VAL(SUBSTR(c变动成绩,1,2)))
MM2 = INT(VAL(SUBSTR(c变动成绩,4,2)))
SS2 = INT(VAL(SUBSTR(c变动成绩,7,2)))
SSS2 = INT(VAL(SUBSTR(c变动成绩,10,3)))

IF SSS1 >= SSS2
   SSS = SSS1 - SSS2
ELSE
   SSS = SSS1 - SSS2 + 1000
   SS1 = SS1 - 1
ENDIF
   
IF SS1 >= SS2
   SS = SS1 - SS2
ELSE
   SS = SS1 - SS2 + 60
   MM1 = MM1 - 1
ENDIF

IF MM1 >= MM2
   MM = MM1 - MM2
ELSE
   MM = MM1 - MM2 + 60
   HH1 = HH1 - 1
ENDIF

HH = HH1 - HH2
IF HH < 0
   MESSAGEBOX("减少变动成绩大于当前成绩,成绩不变!",48,"提示")
   RETURN c当前成绩
ELSE
RETURN PADL(HH,2,"0") + ":" + PADL(MM,2,"0") + ":" + PADL(SS,2,"0") + "." + PADL(SSS,3,"0")
ENDIF
ENDFUNC
2022-07-10 00:43
schtg
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:https://t.me/pump_upp
等 级:贵宾
威 望:67
帖 子:1355
专家分:2534
注 册:2012-2-29
得分:0 
各位大侠,学习啦,谢谢!
2022-07-10 10:27
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
回复 33楼 mywisdom88
通常是转换成数值(秒)进行加减运算后再转换成显示格式

相关 windows API 有:

typedef struct _FILETIME {
    DWORD dwLowDateTime;
    DWORD dwHighDateTime;
} FILETIME, *PFILETIME, *LPFILETIME;
 
typedef struct _SYSTEMTIME {
    WORD wYear;
    WORD wMonth;
    WORD wDayOfWeek;
    WORD wDay;
    WORD wHour;
    WORD wMinute;
    WORD wSecond;
    WORD wMilliseconds;
} SYSTEMTIME, *LPSYSTEMTIME;

FILETIME和SYSTEMTIME都只是记录时间的结构。
GetLocalTime能够得到本地电脑设置时区的时间,得到的类型是SYSTEMTIME的类型。
常用转换函数:
LONG WINAPI CompareFileTime(const FILETIME *lpft1, const FILETIME *lpft2);
BOOL WINAPI FileTimeToSystemTime(const FILETIME *lpft, LPSYSTEMTIME lpst);
BOOL WINAPI SystemTimeToFileTime(const SYSTEMTIME *lpst, LPFILETIME lpft);
BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *lpft, LPFILETIME lpftLocal);
BOOL WINAPI LocalFileTimeToFileTime(const FILETIME *lpftLocal, LPFILETIME lpft);

FILETIME 涉及到64位数值运算,可惜VFP不支持。
2022-07-10 12:13
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
以下是引用mywisdom88在2022-7-10 00:43:15的发言:

c当前 = "32:20:9.419"
c加减 = "-1:8.412"

格式固定规范可简化算法,如:h:m:s
c当前 = "32:20:9.419"
c加减 = "-0:1:8.412"
2022-07-10 14:50
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
以下是引用吹水佬在2022-7-10 12:13:52的发言:

FILETIME 涉及到64位数值运算,可惜VFP不支持。

简单写个模拟64位加减法,可以用来处理 FILETIME 的加减运算
程序代码:
    ** 模拟64位加法
FUNCTION add64(cInt64_a, cInt64_b)
    IF !(LEN(cInt64_a)==8 AND LEN(cInt64_b)==8)
        MESSAGEBOX("调用add64()无效的参数,要求是64位整数(8字节)")
        RETURN ""
    ENDIF
    LOCAL hi_a, lo_a, hi_b, lo_b, flag, hi_i, lo_i, hi_c, lo_c
    hi_a = CTOUINT(RIGHT(cInt64_a,4))
    lo_a = CTOUINT( LEFT(cInt64_a,4))
    hi_b = CTOUINT(RIGHT(cInt64_b,4))
    lo_b = CTOUINT( LEFT(cInt64_b,4))
    lo_i = lo_a + lo_b
    lo_i = CTOUINT(UINTTOC(lo_i,4))    && 取低32位部分,去除溢出部分
    flag = IIF(lo_i<lo_a, 1, 0)        && 检查是否发生了进位
    hi_i = hi_a + hi_b + flag
    RETURN UINTTOC(lo_i,4) + UINTTOC(hi_i,4)
ENDFUNC    

    ** 模拟64位减法
FUNCTION sub64(cInt64_a, cInt64_b)
    IF !(LEN(cInt64_a)==8 AND LEN(cInt64_b)==8)
        MESSAGEBOX("调用sub64()无效的参数,要求是64位整数(8字节)")
        RETURN ""
    ENDIF
    LOCAL hi_a, lo_a, hi_b, lo_b, flag, hi_i, lo_i, hi_c, lo_c
    hi_a = CTOUINT(RIGHT(cInt64_a,4))
    lo_a = CTOUINT( LEFT(cInt64_a,4))
    hi_b = CTOUINT(RIGHT(cInt64_b,4))
    lo_b = CTOUINT( LEFT(cInt64_b,4))
    lo_i = lo_a - lo_b
    flag = IIF(lo_i<0, 1, 0)            && 检查是否发生了借位
    IF flag == 1
        lo_i = 0xffffffff + lo_i + 1
    ENDIF 
    hi_i = hi_a - hi_b - flag
    IF hi_i < 0
        MESSAGEBOX("调用sub64()无效的参数,要求被减数 >= 减数")
        RETURN ""
    ENDIF
    RETURN UINTTOC(lo_i,4) + UINTTOC(hi_i,4)
ENDFUNC    

    * 二进制字符转换为无符号整数
FUNCTION CTOUINT(cNum)
    LOCAL len,i,ret
    len = LEN(cNum)
    IF len == 0
        RETURN NULL
    ENDIF 
    ret = ASC(SUBSTR(cNum,len,1))
    FOR i=len-1 TO 1 STEP -1
        ret = ret*0x100 + ASC(SUBSTR(cNum,i,1))
    ENDFOR
    RETURN ret
ENDFUNC

    ** 无符号整数转换成二进制字符
FUNCTION UINTTOC(uint, len)
    IF uint < 0
        MESSAGEBOX("调用 UINTTOC() 参数无效,要求数值 >= 0")
        RETURN ""
    ENDIF
    LOCAL ret
    ret = ""
    DO WHILE uint != 0
        ret  = ret + CHR(uint % 0x100)
        uint = INT(uint / 0x100)
    ENDDO
    RETURN PADR(ret, len, 0h00)
ENDFUNC


[此贴子已经被作者于2022-7-14 17:00编辑过]

2022-07-11 16:34



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-509515-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.057794 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved