宏算算式高级示例:日期计算器

2017-09-29 12:26:02 NUMKIT.COM  欢迎转载,转载请注明出处

我们将通过创建一个日期计算器,来讲解宏算算式的高级用法。

在阅读这篇文章之前,我们假设您已经掌握了宏算算式的基本用法。 如果您在理解这篇文章时遇到困难,建议您先阅读文章宏算算式初级示例:折扣价格计算器

您可以通过在线计算手机宏算处理宏算算式得到界面。 您还可以登录宏算账户,将宏算算式生成的界面保存为“我创建的”,生成公共链接,甚至发布到算式知识库供其他人使用。

计算时间

在不设置参数的显示形式的情况下,宏算算式中的参数均按照浮点数的方式显示,参数的显示形式和数值形式是一致的。

修饰器view可以控制数值的显示形式。在宏算算式内部进行计算时,所有输入内容都首先被转换成数值形式。 计算完成后,各输出变量会按照其显示类型由数值形式转换为显示形式。

例如,设置参数a的显示形式为“整数”:

view{a:Integer}

a为输入参数,则在参数a对应的输入框中,只允许输入整数值。 若a为输出参数,当计算过程结束,a在结果中显示为其四舍五入后的整数值。

再如,设置参数a的显示形式为“日期”:

view{a:Date}

Date类型的显示格式为 年-月-日。在内部计算过程中,Date采用自1970年1月1日凌晨至当日凌晨间的毫秒数表示。

下面举两个例子来说明这种转换方法: 1. 若a为输入参数,当用户在参数a对应的输入框中输入了内容“2009-05-30”,则在内部计算过程中,a的值为1243641600000。 2. 若a为输出参数,当计算过程结束,a最终被赋值为1243641600000,则参数a在结果中显示为“2009-05-30”。

Integer和Date类型只是修饰器view支持的众多显示类型中的其中两个, 关于所有的显示类型的详细信息可参考宏算定义的修饰器的“修饰器view”部分。

有了修饰器view的支持,我们已经可以编写一个简单的日期计算器:

option{title:"日期计算器";
    comment:"本计算器能计算出从特定日期向后数指定天数后的日期。"}
input{i:"开始日期";n:"天数"}
output{o:"结束日期"}
view{i:Date;n:Integer;o:Date}
o=i+n*24*3600*1000;

以上宏算算式可以生成如下界面:

填写“开始日期”和“天数”,点击“确定”,即可计算出从开始日期向后数指定天数后的“结束日期”。

与Date类似的类型还有Time和DateTime,它们都使用了相似的与数值形式的转换方法(自1970年1月1日凌晨以来的毫秒数)。 宏算还设计了一系列能处理这些时间数值的内置函数,包括now()、now(z)、toDate(t)、toTime(t)、toDateTime(t)、toTimeMs(t)、toDateTimeMs(t)、 getYear(t)、getMonth(t)、getDate(t)、getHour(t)、getMinute(t)、getSecond(t)、getMillisecond(t)、getDay(t)。 关于这些函数的详细信息可参考宏算支持的常量与函数。 因为本节中的示例的计算比较简单,所以暂不会用到以上这些函数。

实现下拉框

现在,我们的“日期计算器”已经具备了基本的功能。但它只支持向后数日,不支持向前数日。 虽然用户可以在“天数”输入框中输入一个负数来实现向前数日,但是这样使用起来非常不自然。 让“日期计算器”同时支持向后数日和向前数日的最佳方案是:添加一个以下拉框形式显示的输入参数,从而可以让用户明确选择是向后还是向前数日。

我们可以在修饰器view中为输入参数指定一个“映射序列(数值)”或者“文本值序列”来让该参数显示为下拉框。 “映射序列(数值)”表示数值与文本间的映射关系。 例如在修饰器view中为输入参数a设定值为[100+10,"北京"][100+21,"上海"][999,"海外"], 则在生成的用户界面中,参数a以下拉框控件的方式显示。下拉框中有“北京”、“上海”、“海外”三个选项。 当用户选择“上海”并点击“确定”开始运算时,a的值为121。 “文本值序列”是“映射序列(数值)”的简写形式。只要“映射序列(数值)”中的数值部分是从0开始的连续整数,就可以简写为这种格式。 例如[0,"美元"][1,"人民币"][2,"欧元"]可以简写为"美元","人民币","欧元"

我们为“日期计算器”引入一个新的输入参数t,设置它以下拉框的方式显示:

view{t:[0,"<请选择>"][1,"向后数日"][2,"向前数日"]}

当然,可以简写为:

view{t:"<请选择>","向后数日","向前数日"}

接下来,在计算部分,我们只要判断参数t的值就知道用户选择了哪一个选项了。

根据不同的情况执行不同的计算步骤可以通过条件相关函数或If-Else结构实现。 关于条件与分支计算的详细用法请参考宏算算式的条件与分支。 本示例将采用两个If-Else结构(省略Else部分)判断参数t的值并分别执行相应的计算步骤:

if(t==1){o=i+n*24*3600*1000;}
if(t==2){o=i-n*24*3600*1000;}

以上代码在参数t的值等于1时(用户选择了“向后数日”),执行语句o=i+n*24*3600*1000;; 在参数t的值等于2时(用户选择了“向前数日”),执行语句o=i-n*24*3600*1000;; 在参数t是其他值(只可能是0)时(用户选择了“<请选择>”),什么也不做。

注意,判断两值是否相等所使用的符号是“两个连续的等号”,如使用t==1判断t和1是否相等。 单个的等号只用在赋值,如使用o=i+n*24*3600*1000;i+n*24*3600*1000的计算结果保存到变量o中。

综合以上内容,修改“日期计算器”的算式为如下所示:

option{title:"日期计算器";
comment:"本计算器能计算出从特定日期向后或向前数指定天数后的日期。"}
input{i:"开始日期";t:"计算方式";n:"天数"}
output{o:"结束日期"}
view{i:Date;t:"<请选择>","向后数日","向前数日";n:Integer;o:Date}
if(t==1){o=i+n*24*3600*1000;}
if(t==2){o=i-n*24*3600*1000;}

以上宏算算式可以生成如下界面:

可以看到,新的“日期计算器”已经支持向后数日和向前数日两种计算方式了。

验证输入

使用修饰器view为输入参数设置显示类型,在一定程度上规范了用户的输入。 例如本“日期计算器”中的“开始日期”只接受“年-月-日”格式的字符串;“计算方式”只接受下拉框中的三选项之一;“天数”只接受整数值。 但是在有些情况下,这些验证规范是不充分的,我们希望对用户的输入进行更严格的验证。

修饰器validate可以进一步为宏算界面添加验证规则。它支持属性alert,可接受的属性值为映射序列(条件)。 映射序列(条件)的格式为[<条件1>,<文本值1>][<条件2>,<文本值2>]...。 修饰器validate会在用户输入完毕点击“确定”时逐条检查错误条件,并在条件通过时弹出相应的错误提示信息。 即,若<条件1>满足,弹出提示<文本值1>;若<条件2>满足,弹出提示<文本值2>...

我们要对“日期计算器”添加验证规则:1. “计算方式”必须选择“向后数日”或“向前数日”之一;2. “天数”不能小于0。即可通过以下代码实现:

validate{alert:[t!=1 and t!=2,"请选择计算方式"][n<0,"天数不能小于0"];}

以上代码中,条件t!=1 and t!=2的含义是“t不等于1 同时 t不等于2”。!=的作用是判断左右两边的值是否不相等and是一个逻辑运算符,当它两边的式子都为真时才返回真。 关于“条件式”的更多信息请参考宏算算式的条件与分支中的“通过If-Else结构实现”章节关于“条件式”的说明。

添加验证规则后,“日期计算器”的算式变为:

option{title:"日期计算器";
comment:"本计算器能计算出从特定日期向后或向前数指定天数后的日期。"}
input{i:"开始日期";t:"计算方式";n:"天数"}
output{o:"结束日期"}
view{i:Date;t:"<请选择>","向后数日","向前数日";n:Integer;o:Date}
validate{alert:[t!=1 and t!=2,"请选择计算方式"][n<0,"天数不能小于0"];}
if(t==1){o=i+n*24*3600*1000;}
if(t==2){o=i-n*24*3600*1000;}

处理以上宏算算式重新生成宏算界面。当用户没有选择“计算方式”(此时t为0)时,点击“确定”按钮将弹出错误提示“请选择计算方式”; 当用户选择了“计算方式”但是输入了小于0的“天数”时,点击“确定”按钮将弹出错误提示“天数不能小于0”。

设定初始值

在“日期计算器”界面初始显示时或点击“重置”按钮后,“开始日期”输入框的内容是“1970-01-01”,“计算方式”下拉框选中的是第一个选项“<请选择>”, “天数”输入框的内容是“0”。对于设定了不同显示类型的各种输入参数,宏算界面都会为它们分配默认的初始值,通常是“0对应的显示形式”或者是“第一个选项”(下拉框)。

修饰器default可以控制界面中各种输入参数的初始值。 我们将使用这个修饰器把“开始日期”的初始值设置为“今天”,把“计算方式”的初始值设置为第二个选项“向后数日”。代码如下:

default{i:toDate(now());t:1}

以上代码设置输入参数i的初始值为toDate(now())。其中now()和toDate(t)是宏算内置的用于支持时间相关计算的函数。 now()返回当前时间自1970年1月1日0时以来的毫秒数; toDate(t)接受“自1970年1月1日0时以来经过的毫秒数”作为参数,返回传入的参数减去自当天凌晨经过的毫秒数后得到的数值(即返回当天的日期的数值形式)。 两函数嵌套起来调用,也就是toDate(now())的返回值就是“今天”这个日期的数值形式。

另外,以上代码还设置输入参数t的初始值为1。 注意,这里的值1指的是下拉框第二个选项(从0开始计数),并非指参数t的值。 假设在修饰器view中为输入参数t设置的显示类型为[100+10,"北京"][100+21,"上海"][999,"海外"], 则要在修饰器default中为输入参数t设置初始值为第二个选项“上海”仍然要使用1表示,使用121表示是错误的。

添加初始值设定后,“日期计算器”的算式变为:

option{title:"日期计算器";
comment:"本计算器能计算出从特定日期向后或向前数指定天数后的日期。"}
input{i:"开始日期";t:"计算方式";n:"天数"}
output{o:"结束日期"}
view{i:Date;t:"<请选择>","向后数日","向前数日";n:Integer;o:Date}
validate{alert:[t!=1 and t!=2,"请选择计算方式"][n<0,"天数不能小于0"];}
default{i:toDate(now());t:1}
if(t==1){o=i+n*24*3600*1000;}
if(t==2){o=i-n*24*3600*1000;}

以上宏算算式可以生成如下界面:

可以看到,新的“日期计算器”在界面初始显示时或点击“重置”按钮后,“开始日期”输入框的内容是今天的日期,“计算方式”下拉框选中的是第二个选项“向后数日”。

完成

至此,我们的“日期计算器”已经制作完成了。

使用宏算算式生成的界面称为“宏算界面”。宏算提供多样的方式来管理您创建的宏算界面。 您可以将创建的宏算界面保存到您的账户中仅供自己使用,也可以生成公共链接或发布到算式知识库中供其他人使用,还可以生成HTML格式并下载等。 您还可以下载手机宏算,仅将创建的宏算界面离线保存在手机上,通过二维码在手机间传输文档等。 要详细了解宏算界面的相关操作,请参考文档宏算界面操作指南