線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1990
推到 Plurk!
推到 Facebook!

時間的運算,如何扣除休息時間

答題得分者是:Reiji
lovemari
中階會員


發表:134
回覆:224
積分:76
註冊:2005-08-18

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-07-21 13:36:19 IP:122.116.xxx.xxx 訂閱
小弟寫了以下算式

TO_CHAT(IN_TIME,HI:MM:SS) ----> 9:00:00
TO_CHAT(OUT_TIME,HI:MM:SS) --> 14:00:00

(OUT_TIME - IN_TIME) * 1440 -------> 5 小時

但其實中間 12:00 - 13:00 是休息時間 我該怎樣加入條件
才可以讓結果會自動扣除60分鐘


------
Program : Delphi 7
DataBase : Oracle 9i
Client : ClientDataSet
編輯記錄
lovemari 重新編輯於 2008-07-21 13:51:38, 註解 無‧
Reiji
初階會員


發表:30
回覆:57
積分:32
註冊:2008-06-26

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-07-21 14:27:27 IP:61.219.xxx.xxx 訂閱
為了簡單化
我暫且先將計算相減的公式以P代替
我的作法是
首先要去歸納出IN_TIME和OUT_TIME的幾種情況,
然後確定哪幾種為P-1,哪些不用
然後利用decode去判斷,一層一層的解出來


[code sql]
decode(round(TO_CHAR(IN_TIME,'HH')/12,0),0,
decode(round(TO_CHAR(OUT_TIME,'HH')/12,0), 1, decode(round(TO_CHAR(OUT_TIME,'HH')/13,0), 1, P - 1, P), P),
decode(round(TO_CHAR(IN_TIME,'HH')/13,0),1,decode(round(TO_CHAR(OUT_TIME,'HH')/13,0), 1, P, 0),decode(round(TO_CHAR(OUT_TIME,'HH')/13,0), 1, P - 1, P)))

[/code]

P的結果我是以小時來算,所以減1
------
永遠都是新手
編輯記錄
Reiji 重新編輯於 2008-07-21 14:28:29, 註解 無‧
lovemari
中階會員


發表:134
回覆:224
積分:76
註冊:2005-08-18

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-07-22 13:33:56 IP:122.116.xxx.xxx 訂閱
大大  我照你方式解

結果跑出來 時間跟直接相減一樣

沒有扣除中間那休息60分鐘耶

IN_TIME : 11:40
OUT_TIME : 13:40

應該只有 1HR 結果跑出來 還是2HR 耶
------
Program : Delphi 7
DataBase : Oracle 9i
Client : ClientDataSet
lovemari
中階會員


發表:134
回覆:224
積分:76
註冊:2005-08-18

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-07-22 13:36:12 IP:122.116.xxx.xxx 訂閱
沒事= =

我剛才發現 我忘記修改分鐘

你是 -1 而已 改成-60 就可以了

哈 感謝大大呢
------
Program : Delphi 7
DataBase : Oracle 9i
Client : ClientDataSet
編輯記錄
lovemari 重新編輯於 2008-07-22 13:36:33, 註解 無‧
lovemari
中階會員


發表:134
回覆:224
積分:76
註冊:2005-08-18

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-07-22 14:42:48 IP:122.116.xxx.xxx 訂閱
大大 我解決了 12:00-13:00
我看算式 是利用/12 的結果 來算是否要扣除

那小弟現在又有 10:00 - 10:05 跟 15:00 - 15:10 的休息時間要扣除
請問能教我如何下指令嗎
------
Program : Delphi 7
DataBase : Oracle 9i
Client : ClientDataSet
Reiji
初階會員


發表:30
回覆:57
積分:32
註冊:2008-06-26

發送簡訊給我
#6 引用回覆 回覆 發表時間:2008-07-22 17:17:50 IP:61.219.xxx.xxx 訂閱
可以用個偷懶的方法作:
如果上班時間是9~14點
那麼一定包括了10:00~10:05和15:00~15:10
直接把得到的時數去減掉15分(因為你是用分來計算,所以應該可以直接減)
同理
依照上班時段去判斷是否有超過15:10、早於10:00
試著畫看看線段圖來想出多種上班時段的可能
再一一破解各種加減這兩個休息時間的方法

把decode再加進去減去中午的decode中應該就可以完成
只是眼睛和腦袋很容易打結就是了
------
永遠都是新手
lovemari
中階會員


發表:134
回覆:224
積分:76
註冊:2005-08-18

發送簡訊給我
#7 引用回覆 回覆 發表時間:2008-07-23 15:47:00 IP:122.116.xxx.xxx 訂閱
呵呵 大大謝謝你撥空來回文

大大如果是全天候的 直接-15分鐘就好

可是難就難在有些並非整天 有些可能只有早上有些只有下午

那早上又未必會超過10:05 (就是說不用扣除5分)

那我看了大大之前的12:00-13:00 是利用除12 來看整數是否要扣除60分的

那現在10:00 - 10:05 , 15:00 - 15:10 小弟時在想不出該怎麼下

唯一有想到的是利用 IF IN_TIME > 10:00 AND OUT_TIME > 10:05 THEN TIME - 5
IF IN_TIME > 15:00 AND OUT_TIME > 15:10 THEN TIME - 10

可是我再寫 這段又會出現錯誤 我是用StringGrid.Cell[ x,y ] 好頭痛QQ
------
Program : Delphi 7
DataBase : Oracle 9i
Client : ClientDataSet
Reiji
初階會員


發表:30
回覆:57
積分:32
註冊:2008-06-26

發送簡訊給我
#8 引用回覆 回覆 發表時間:2008-07-23 17:50:49 IP:61.219.xxx.xxx 訂閱
估計你是在寫刷卡系統?

一般公司通常不會去扣除休息時間,所以在計算上也不會去扣這15分
不過既然要去算,那一定會很複雜
我試著寫看看,不過並沒有實際RUN過,用用看吧

先前的寫法並沒有把分也算入,所以直接以中午1小時來計算
你提這個休息時間的問題,讓我想到中午有分的情況(ex:IN_TIME=12:25)
所以重新改寫一下,不過IN_TIME=8:33這種我就不予理會了,這要看你想要怎麼去算
在這裡我當IN_TIME和OUT_TIME一率為準點0分,有需要可以自己再改寫
為了讓自己腦袋清楚,我分段寫,自己把它拼起來用吧^^


[code sql]
P=OUT_TIME - IN_TIME
先判斷上班的時間是否是上午
decode(round(TO_CHAR(IN_TIME,'HH')<12,A,B)

A:
若是上午則判斷上班時間為10點前後,10點前就一定會扣到5分鐘,10點則判斷是否小於10:05,

若不是10點(ex:11點)則不扣
decode(round(TO_CHAR(IN_TIME,'HH')<10, C, //如果上班時間為10前就進行C判斷
decode(round(TO_CHAR(IN_TIME,'HH')=10, //如果上班時間是10點則判斷是否小於5分
decode(round(TO_CHAR(IN_TIME,'MM')<5,D(註),D-5),D))

註:這裡有個矛盾,造理說10:00以後都要扣5分鐘才對,不過如果10:00刷卡,有公司還是會算這5
分鐘進去,所以看你要怎麼去寫
B:
若是下午上班則再判斷,12點上班則要減去12點上班的時間,從13點開始計算
decode(round(TO_CHAR(IN_TIME,'HH')>=13,F,F-(60-round(TO_CHAR(IN_TIME,'MM')))


C:在上班時間<10點的情況下判斷下班時間,如果到10點則不需扣,到12點就扣5,到15點扣65
(60 5),超過15點就扣80(60 5 15)
decode(round(TO_CHAR(OUT_TIME,'HH')<=10,P,
decode(round(TO_CHAR(OUT_TIME,'HH')<=12,P-5,
decode(round(TO_CHAR(OUT_TIME,'HH')<=15,P-65,P-80)))
D:
decode(round(TO_CHAR(OUT_TIME,'HH')<=12,P,
decode(round(TO_CHAR(OUT_TIME,'HH')<=15,P-60,P-75))
E:
decode(round(TO_CHAR(OUT_TIME,'HH')<=12,P-5,
decode(round(TO_CHAR(OUT_TIME,'HH')<=15,P-65,P-80))
F:
decode(round(TO_CHAR(OUT_TIME,'HH')<=15,P,P-10)

[/code]

發現我語法有錯,加上round四捨五入有些問題
修改為以下程式碼


[code sql]
P=OUT_TIME - IN_TIME
先判斷上班的時間是否是上午
decode(floor(TO_CHAR(IN_TIME,'HH')/12),0,A,B)
A:
若是上午則判斷上班時間為10點前後,10點前就一定會扣到5分鐘,10點則判斷是否小於10:05,
若不是10點(ex:11點)則不扣
decode(floor(TO_CHAR(IN_TIME,'HH')/10),0, C, //如果上班時間為10前就進行C判斷
decode(TO_CHAR(IN_TIME,'HH'),10, //如果上班時間是10點則判斷是否小於5分
decode(floor(TO_CHAR(IN_TIME,'MM')/5),0,D(註),D-5),D))
註:這裡有個矛盾,造理說10:00以後都要扣5分鐘才對,不過如果10:00刷卡,有公司還是會算這5
分鐘進去,所以看你要怎麼去寫
B:
若是下午上班則再判斷,12點上班則要減去12點上班的時間,從13點開始計算
decode(floor(TO_CHAR(IN_TIME,'HH')/13),1,E,E-(60-TO_CHAR(IN_TIME,'MM')))

C:在上班時間<10點的情況下判斷下班時間,如果到10點則不需扣,到12點就扣5,到15點扣65
(60 5),超過15點就扣75(60 5 10)
decode(floor(TO_CHAR(OUT_TIME,'HH')/10),0,P,
decode(floor(TO_CHAR(OUT_TIME,'HH')/12),0,P-5,
decode(floor(TO_CHAR(OUT_TIME,'HH')/15),0,P-65,P-75)))
D:
decode(floor(TO_CHAR(OUT_TIME,'HH')/12),0,P,
decode(floor(TO_CHAR(OUT_TIME,'HH')/15),0,P-60,P-70))
E:
decode(floor(TO_CHAR(OUT_TIME,'HH')/15),0,P,P-10)

[/code]
------
永遠都是新手
編輯記錄
Reiji 重新編輯於 2008-07-29 11:10:50, 註解 修改程式碼內容‧
lovemari
中階會員


發表:134
回覆:224
積分:76
註冊:2005-08-18

發送簡訊給我
#9 引用回覆 回覆 發表時間:2008-07-24 10:50:10 IP:122.116.xxx.xxx 訂閱
大大 可以利用修改你之前12點 13點那格式去判斷 要不要扣除休息時間嗎
我參照你之前格式修改 結果卻沒有扣除



[code delphi]
decode(round(TO_CHAR(IN_TIME,'HHMM')/1000,0),0,
decode(round(TO_CHAR(OUT_TIME,'HHMM')/1000,0), 1, decode(round(TO_CHAR(OUT_TIME,'HHMM')/1005,0), 1, P - 5, P), P),
decode(round(TO_CHAR(IN_TIME,'HHMM')/1005,0),1,decode(round(TO_CHAR(OUT_TIME,'HHMM')/1005,0), 1, P, 0),decode(round(TO_CHAR(OUT_TIME,'HHMM')/1005,0), 1, P - 5, P)))
[/code]
------
Program : Delphi 7
DataBase : Oracle 9i
Client : ClientDataSet
編輯記錄
lovemari 重新編輯於 2008-07-24 10:51:04, 註解 無‧
lovemari 重新編輯於 2008-07-24 10:51:40, 註解 無‧
lovemari 重新編輯於 2008-07-24 10:51:58, 註解 無‧
Reiji
初階會員


發表:30
回覆:57
積分:32
註冊:2008-06-26

發送簡訊給我
#10 引用回覆 回覆 發表時間:2008-07-25 11:40:08 IP:61.219.xxx.xxx 訂閱
不曉得你的公式p為何?
是(out_time - in_time) *1440嗎?
若是,那麼p-5的部分你是怎麼寫呢?
是((out_time - in_time) *1440) -5 還是 (out_time - in_time - 5) *1440 ?

另外我問個笨問題,為什麼要x1440?
out_time - in_time會出來什麼@@?
------
永遠都是新手
lovemari
中階會員


發表:134
回覆:224
積分:76
註冊:2005-08-18

發送簡訊給我
#11 引用回覆 回覆 發表時間:2008-07-25 15:25:55 IP:122.116.xxx.xxx 訂閱
因為我用了 TO_CHAR 單位是小時

X1440 = 60分X 每天24小時

把單位換算成分 我要精準到分這各單位


沒錯 P = (OUT_TIME - IN_TIME) * 1440

我寫這樣 ((out_time - in_time) *1440) -5 換算成分鐘之後再-5

這是我現在寫的結果是沒有扣除5


[code delphi]
decode(round(TO_CHAR(IN_TIME,'HHMI')/1000,0),0,
decode(round(TO_CHAR(OUT_TIME,'HHMI')/1000,0), 1, decode(round(TO_CHAR(OUT_TIME,'HHMI')/1005,0), 1, P - 5, P), P),
decode(round(TO_CHAR(IN_TIME,'HHMI')/1005,0),1,decode(round(TO_CHAR(OUT_TIME,'HHMI')/1005,0), 1, P, 0),decode(round(TO_CHAR(OUT_TIME,'HHMI')/1005,0), 1, P - 5, P)))
[/code]

PS. 我之前打錯了 TO_CHAR 格式應該是 YYYYMMDD 年月日 HHMISS 時分秒



===================引 用 Reiji 文 章===================
不曉得你的公式p為何?
是(out_time - in_time) *1440嗎?
若是,那麼p-5的部分你是怎麼寫呢?
是((out_time - in_time) *1440) -5 還是 (out_time - in_time - 5) *1440 ?

另外我問個笨問題,為什麼要x1440?
out_time - in_time會出來什麼@@?
------
Program : Delphi 7
DataBase : Oracle 9i
Client : ClientDataSet
編輯記錄
lovemari 重新編輯於 2008-07-25 15:26:42, 註解 無‧
lovemari 重新編輯於 2008-07-25 15:32:54, 註解 無‧
lovemari
中階會員


發表:134
回覆:224
積分:76
註冊:2005-08-18

發送簡訊給我
#12 引用回覆 回覆 發表時間:2008-07-29 11:20:07 IP:122.116.xxx.xxx 訂閱
哈 感謝大大點醒我了
因為FLOOR 我不是很懂用法 我改用TRUNC
結果成功了 有扣除休息時間了 感謝啦
那想順便問兩各小問題
1.FLOOR 的參數該怎麼設 我跑這段出現參數錯誤
我只會設定ROUND跟TRUNC 想學FLOOR 能舉各例子嗎?
2.我想把扣除休息時間的全部弄成一各欄位
實在不是很好用 因為有三段
10:00-10:05 , 12:00-13:00 , 15:00- 15:10
我是把你给我的算是分成三段,然後用逗號結合
可是都會出現錯誤,或者變成三段時間,不曉得該
怎麼做耶
PS.由衷感謝你放假完還上線回答 大大你真的是各好人 小弟在此先祝福你事業順心,身體健康..
------
Program : Delphi 7
DataBase : Oracle 9i
Client : ClientDataSet
編輯記錄
lovemari 重新編輯於 2008-07-29 11:21:16, 註解 無‧
Reiji
初階會員


發表:30
回覆:57
積分:32
註冊:2008-06-26

發送簡訊給我
#13 引用回覆 回覆 發表時間:2008-07-29 11:43:47 IP:61.219.xxx.xxx 訂閱
1.
floor(12.33333)得12
floor(12.77777)得12
floor是用於無條件捨去小數位,所以無參數

順道補充一個Ceil,與floor一樣不需參數,它是無條件進位

2.
哈...不太懂你的意思...


p.s.我也還在學,所以是邊回答你邊學著的,別客氣
------
永遠都是新手
lovemari
中階會員


發表:134
回覆:224
積分:76
註冊:2005-08-18

發送簡訊給我
#14 引用回覆 回覆 發表時間:2008-07-29 13:23:54 IP:122.116.xxx.xxx 訂閱
抱歉抱歉 我敘述一下  (剛剛試過FLOOR效果一樣)

就是三段我們之前討論的改法
10:00 - 10:05
12:00 - 13:00
15:00 - 15:10
三段分開跑都是正常 那我只是要跑一各FIELD而以.... 我試過用逗號之類的 不曉得如何結合


[code delphi]

//第一段
decode(round(TO_CHAR(IN_TIME,'HH')/12,0),0,
decode(round(TO_CHAR(OUT_TIME,'HH')/12,0), 1, decode(round(TO_CHAR(OUT_TIME,'HH')/13,0), 1, P - 1, P), P),
decode(round(TO_CHAR(IN_TIME,'HH')/13,0),1,decode(round(TO_CHAR(OUT_TIME,'HH')/13,0), 1, P, 0),decode(round(TO_CHAR(OUT_TIME,'HH')/13,0), 1, P - 1, P)))
//第二段
decode(floor(TO_CHAR(IN_TIME,'HHMI')/1000),0,
decode(floor(TO_CHAR(OUT_TIME,'HHMI')/1000), 1, decode(floor(TO_CHAR(OUT_TIME,'HHMI')/1005), 1, P - 1, P), P),
decode(floor(TO_CHAR(IN_TIME,'HHMI')/1005),1,decode(floor(TO_CHAR(OUT_TIME,'HHMI')/1005), 1, P, 0),decode(floor(TO_CHAR(OUT_TIME,'HHMI')/1005), 1, P - 1, P)))
//第三段
decode(floor(TO_CHAR(IN_TIME,'HHMI')/1500),0,
decode(floor(TO_CHAR(OUT_TIME,'HHMI')/1500), 1, decode(floor(TO_CHAR(OUT_TIME,'HHMI')/1510), 1, P - 1, P), P),
decode(floor(TO_CHAR(IN_TIME,'HHMI')/1510),1,decode(floor(TO_CHAR(OUT_TIME,'HHMI')/1510), 1, P, 0),decode(floor(TO_CHAR(OUT_TIME,'HHMI')/1510), 1, P - 1, P)))

"總結時間"
[/code]
------
Program : Delphi 7
DataBase : Oracle 9i
Client : ClientDataSet
編輯記錄
lovemari 重新編輯於 2008-07-29 13:24:43, 註解 無‧
Reiji
初階會員


發表:30
回覆:57
積分:32
註冊:2008-06-26

發送簡訊給我
#15 引用回覆 回覆 發表時間:2008-07-29 17:18:30 IP:61.219.xxx.xxx 訂閱
我想你的第一段應該是p-60(分)吧?

如果你一定要用分開去計算的方式來算,
我建議改為這樣:

第一段的p改為0,p-60改為60(12:00 - 13:00)
第二段的p為0,p-5為5(10:00 - 10:05)
第三段的p為0,p-10為10(15:00 - 15:10)

總結就是(out_time-in_time)-(第一段的結果 第二段的結果 第三段的結果)


也就是把這三段程式改為計算需要減去的時間
然後總結就是把算出來需要減去的時間減掉,就能得到你想要的結果

不過這種寫法我感覺或許在資料量大時會比較耗時間 耗資源
------
永遠都是新手
編輯記錄
Reiji 重新編輯於 2008-07-29 17:20:52, 註解 無‧
lovemari
中階會員


發表:134
回覆:224
積分:76
註冊:2005-08-18

發送簡訊給我
#16 引用回覆 回覆 發表時間:2008-07-29 19:11:02 IP:122.116.xxx.xxx 訂閱
天阿 好怪的問題喔

我早上提到的用 FLOOR 去減掉10:00-10:05 的5分

可是套用在 15:00 - 15:10 就完全不行

改成 ROUND , TRUNC 都不會減

快暈倒了
------
Program : Delphi 7
DataBase : Oracle 9i
Client : ClientDataSet
lovemari
中階會員


發表:134
回覆:224
積分:76
註冊:2005-08-18

發送簡訊給我
#17 引用回覆 回覆 發表時間:2008-07-29 20:22:28 IP:122.116.xxx.xxx 訂閱

呵呵

大大 我就是想問這段

(第一段的結果 第二段的結果 第三段的結果)
該怎麼結合 因為是三段很長的算式 要把三段合成一段 是全部放在一起在用括號嗎??

===================引 用 Reiji 文 章===================
我想你的第一段應該是p-60(分)吧?

如果你一定要用分開去計算的方式來算,
我建議改為這樣:

第一段的p改為0,p-60改為60(12:00 - 13:00)
第二段的p為0,p-5為5(10:00 - 10:05)
第三段的p為0,p-10為10(15:00 - 15:10)

總結就是(out_time-in_time)-(第一段的結果 第二段的結果 第三段的結果)


也就是把這三段程式改為計算需要減去的時間
然後總結就是把算出來需要減去的時間減掉,就能得到你想要的結果

不過這種寫法我感覺或許在資料量大時會比較耗時間 耗資源
------
Program : Delphi 7
DataBase : Oracle 9i
Client : ClientDataSet
Reiji
初階會員


發表:30
回覆:57
積分:32
註冊:2008-06-26

發送簡訊給我
#18 引用回覆 回覆 發表時間:2008-07-30 09:47:31 IP:61.219.xxx.xxx 訂閱
1.是的,把它全部用括號綜合起來

2.不論是floor、round還是trunc,因為時間不是十進位,所以用小數點來算是容易就有出錯的問題
一兩個時間或許可以順利算出來,但再更多不同的時間情況下一定會有因為小數點的誤差而造成的錯誤
還是,你是說同樣的時間區段你跑的結果不一樣呢?
------
永遠都是新手
lovemari
中階會員


發表:134
回覆:224
積分:76
註冊:2005-08-18

發送簡訊給我
#19 引用回覆 回覆 發表時間:2008-07-30 12:59:12 IP:122.116.xxx.xxx 訂閱

我好笨喔

後來想到 15:00 - 15:10 是24進位

轉換成為24進位之後 就可以去扣除了

===================引 用 lovemari 文 章===================
天阿 好怪的問題喔

我早上提到的用 FLOOR 去減掉10:00-10:05 的5分

可是套用在 15:00 - 15:10 就完全不行

改成 ROUND , TRUNC 都不會減

快暈倒了
------
Program : Delphi 7
DataBase : Oracle 9i
Client : ClientDataSet
lovemari
中階會員


發表:134
回覆:224
積分:76
註冊:2005-08-18

發送簡訊給我
#20 引用回覆 回覆 發表時間:2008-07-30 13:43:06 IP:122.116.xxx.xxx 訂閱
我試過用

假設 A = P -60 公式
B = P - 5
C = P -10

我寫成 (A,B,C) 這樣 會一值出現 遺漏右括弧

然後我一值填右括弧 結果不變 還是錯誤耶
------
Program : Delphi 7
DataBase : Oracle 9i
Client : ClientDataSet
lovemari
中階會員


發表:134
回覆:224
積分:76
註冊:2005-08-18

發送簡訊給我
#21 引用回覆 回覆 發表時間:2008-07-30 19:21:13 IP:122.116.xxx.xxx 訂閱
哈 我懂你意思了
但我是改成
(A B C) - (OUT_TIME - IN_TIME)X2
因為A B C 等於三份(一份我要兩份多餘)
所以-2xTIME
謝謝大大
------
Program : Delphi 7
DataBase : Oracle 9i
Client : ClientDataSet
系統時間:2024-09-10 5:41:36
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!