很多时候你需要去计算两个不同时间之间的差值,例如我们计算上次的登陆到现在有多长时间了.我们有很多办法可以完成这个操作,比如去写一些代码,好像没有比这更好的办法了!如果你登陆的时间不是凌晨,那就需要在你能利用一些函数和表达式 去解析这个登陆的时间,然后计算他们的不同.在以下例子中,我将为大家展示一个利用表达式去完成所需要的计算任务.我们鼓励大家多用表达式去实现一些简单的逻辑运算而不是全靠编程.
注意,如果你选择在这个例子上拷贝/粘贴表达式,你可以点击默认值框后面的FX按钮,确认他在你粘贴前的状态是"Exit XPath"状态.
首先,我们来创建数据结构
1、添加一个4列的重复表在你的视图中.
2、重命名这些区域然后改变他们的数据类型.
Name | Data Type |
myDate | Date (date), Format: *3/14/2001 |
StartTime | Time (time), Format: *9:46 AM |
EndTime | Time (time), Format: *9:46 AM |
ActualTime | Text (string) |
3、改变第一个表格中的区域为一个日期选择框
4、在这个重复组里添加两个额外的区域(仅限于数据源中,这些将不显示在视图上,他们的作用是帮助计算的)
Name | Data Type |
ElapsedTime | Text (string) |
TotalMinutes | Decimal (double) |
5、最后在添加一个计算所有登陆汇总的区域-他将添加到myFields节点下,而不是重复节点。
Name | Data Type |
TotalTime | Text (string) |
你的数据结构显示如下:
你的表单应该像这个样子:
我们开始在这个结构中添加表达式!
第一步,我们需要去转换StartTime和EndTime的值到分钟--这个换算相对简单。我们当然不允许执行StartTime和EndTime其中任何一个区域为空的值了。所以,需要执行“条件声明”,我们将在以后的对这个逻辑进行讲解。
第一步:解析小时和分钟
1、我们首先需要去解析小时,然后把他转换为分钟。具体方法是小时乘以60。我们可以在时间区域中利用“substring-before”函数和冒号之间取道:
substring
-
before(..
/
my:EndTime,
"
:
"
)
*
60
)
substring
-
before(..
/
my:StartTime,
"
:
"
)
*
60
2、我们取到各自的值,这时候当时间值存贮在XML下,他们存储的格式为HH:MM:SS。这时候你仅仅需要“分钟”这一部分,我们只好利用一个结合了"substring-before"和"substring-after"的函数取道进入“after”的第一个冒号和“before”的最后一个冒号中间的值。
substring
-
before(substring
-
after(..
/
my:EndTime,
"
:
"
),
"
:
"
)
substring
-
before(substring
-
after(..
/
my:StartTime,
"
:
"
),
"
:
"
)
3、现在,我们去看这些表达式汇总在一起石什么样子,这时候,我们就可以获得各个登陆时间和总的时间了:
((substring
-
before(..
/
my:EndTime,
"
:
"
)
*
60
)
+
substring
-
before(substring
-
after(..
/
my:EndTime,
"
:
"
),
"
:
"
))
((substring
-
before(..
/
my:StartTime,
"
:
"
)
*
60
)
+
substring
-
before(substring
-
after(..
/
my:StartTime,
"
:
"
),
"
:
"
))
4、继续思考,有一些情况我们的表达式是不能执行的,比如,StartTime或者是EndTime区域是空值,或者是EndTime总值小于StartTime总值.这些情况我们我们将利用"substring"函数对这些控件进行条件上的关联.substring函数有以下的语法规则.
substring([String Value], [Starting Position], [Condition
/
Length])
5/在substring函数中合并我们的表达式,下面就是写好的样子:
Substring([EndTime – StartTime],
1
, EndTime
!=
“” and StartTime
!=
“”)
EndTime 表达式
((substring
-
before(..
/
my:EndTime,
"
:
"
)
*
60
)
+
substring
-
before(substring
-
after(..
/
my:EndTime,
"
:
"
),
"
:
"
))
StartTime 表达式
((substring
-
before(..
/
my:StartTime,
"
:
"
)
*
60
)
+
substring
-
before(substring
-
after(..
/
my:StartTime,
"
:
"
),
"
:
"
))
回到开始的位置:1
条件表达式(如果是正确的,我们需要返回这个表达式的长度,那么,我们利用"string-length"函数取活的我们初始化表达式的长度)
(..
/
my:StartTime
!=
""
and ..
/
my:EndTime
!=
""
)
*
string
-
length(((substring
-
before(..
/
my:EndTime,
"
:
"
)
*
60
)
+
substring
-
before(substring
-
after(..
/
my:EndTime,
"
:
"
),
"
:
"
))
-
((substring
-
before(..
/
my:StartTime,
"
:
"
)
*
60
)
+
substring
-
before(substring
-
after(..
/
my:StartTime,
"
:
"
),
"
:
"
)))
我们在TotalMinutes区域中的final 表达式将是以下的样子:
substring(((substring-before(../my:EndTime, ":") * 60) + substring-before(substring-after(../my:EndTime, ":"), ":")) - ((substring-before(../my:StartTime, ":") * 60) + substring-before(substring-after(../my:StartTime, ":"), ":")), 1, (../my:StartTime != "" and ../my:EndTime != "") * string-length(((substring-before(../my:EndTime, ":") * 60) + substring-before(substring-after(../my:EndTime, ":"), ":")) - ((substring-before(../my:StartTime, ":") * 60) + substring-before(substring-after(../my:StartTime, ":"), ":"))))
第二步:转换Total Minutes的结果为小时和和分钟
这里要讲到的表达式将与我们之前用到的有相同的逻辑基础:首先分解total minutes区域的结果以60为进制计算出流逝了多少小时。如果得出的结果出现小数(比如90分钟/60=1.5),想在小时状态下解释小数点后面的值我们可以利用“mod”函数取返回相应的分钟。
1)我们需要以60为进制分离TotalMinutes区域的值为多少小时;我们同样需要去检查,结果值中是否包含了小数点。我们这部分首先利用的表达式将是“substring”函数我们还能利用它去关联一些条件文本。所谓的条件文本,我们将利用“contains”函数去看结果中是否包含小数点:
contains(../my:TotalMinutes div 60, ".")
我们最初的表达式如下:如果结果值中包含了小数点,我们就可以利用“concat”函数去解释这个值,一个冒号与TotalMinutes60进制的值之间。
substring(concat(substring-before(../my:TotalMinutes div 60, "."), ":", ../my:TotalMinutes mod 60), 1, contains(../my:TotalMinutes div 60, ".") * string-length(concat(substring-before(../my:TotalMinutes div 60, "."), ":", ../my:TotalMinutes mod 60)))
2)如果结果表达式中没有包含小数点,则我们将直接写上冒号,在TotalMinutes值后面加60:
substring(concat(../my:TotalMinutes div 60, ":", ../my:TotalMinutes mod 60), 1, not(contains(../my:TotalMinutes div 60, ".")) * string-length(concat(../my:TotalMinutes div 60, ":", ../my:TotalMinutes mod 60)))
3)我们计算ElapsedTime区域的final表达式显示如下:
concat(substring(concat(substring-before(../my:TotalMinutes div 60, "."), ":", ../my:TotalMinutes mod 60), 1, contains(../my:TotalMinutes div 60, ".") * string-length(concat(substring-before(../my:TotalMinutes div 60, "."), ":", ../my:TotalMinutes mod 60))), substring(concat(../my:TotalMinutes div 60, ":", ../my:TotalMinutes mod 60), 1, not(contains(../my:TotalMinutes div 60, ".")) * string-length(concat(../my:TotalMinutes div 60, ":", ../my:TotalMinutes mod 60))))
第三步:关于ActualTime区域
这里是写在ElapsedTime区域中的表达式,如果时间结果小于10,只返回单个值(比如0:9)。因为这样,所以我们要在小于10的值作一个条件格式,比如在这个值前面加个“0”。
这里我们需要利用“string-length”函数取识别string冒号前面的长度。如果长度是2(分钟肯定比9大)则直接与小时管理,一个冒号然后是分钟。如果长度是1(分钟肯定比10小)则需要,一个冒号和一个0(“:0”)然后是分钟。就像下面,我们将利用“substring”函数取识别并返回值:
concat(substring(concat(substring-before(../my:ElapsedTime, ":"), ":", substring-after(../my:ElapsedTime, ":")), 1, (string-length(substring-after(../my:ElapsedTime, ":")) = 2) * string-length(concat(substring-before(../my:ElapsedTime, ":"), ":", substring-after(../my:ElapsedTime, ":")))), substring(concat(substring-before(../my:ElapsedTime, ":"), ":0", substring-after(../my:ElapsedTime, ":")), 1, (string-length(substring-after(../my:ElapsedTime, ":")) = 1) * string-length(concat(substring-before(../my:ElapsedTime, ":"), ":0", substring-after(../my:ElapsedTime, ":")))))
第四步:创建TotalTime表达式,为时刻汇总elapsed time
最后,我们来创建一个TotalTime表达式--这是一个类似于ActualTime表达式,除了我们将利用“sum”函数取获取总数:
concat(substring(concat((sum(../my:group1/my:group2/my:TotalMinutes) - sum(../my:group1/my:group2/my:TotalMinutes) mod 60) div 60, ":", sum(../my:group1/my:group2/my:TotalMinutes) mod 60), 1, (sum(../my:group1/my:group2/my:TotalMinutes) mod 60 > 9) * string-length(concat((sum(../my:group1/my:group2/my:TotalMinutes) - sum(../my:group1/my:group2/my:TotalMinutes) mod 60) div 60, ":", sum(../my:group1/my:group2/my:TotalMinutes) mod 60))), substring(concat((sum(../my:group1/my:group2/my:TotalMinutes) - sum(../my:group1/my:group2/my:TotalMinutes) mod 60) div 60, ":0", sum(../my:group1/my:group2/my:TotalMinutes) mod 60), 1, (sum(../my:group1/my:group2/my:TotalMinutes) mod 60
<
10
) * string-length(concat((sum(../my:group1/my:group2/my:TotalMinutes) - sum(../my:group1/my:group2/my:TotalMinutes) mod 60) div 60, ":0", sum(../my:group1/my:group2/my:TotalMinutes) mod 60))))
第五步:测试
输入开始和结束时间,例如8:00AM和5:00PM ActualTime则显示9:00。如果继续在后面添加,则TotalTime区域将汇总这些值。