【帆软Report】实用公式技巧其一:时间与日期

一、概述

在帆软开发过程中,经常会遇到需要格式化处理日期或传参的需求或场景,本文总结了帆软提供的时间与日期处理函数的一些实用技巧。

二、技术调研

2.1 帆软官方文档

日期和时间函数概述:官方文档链接

2.2 常用的日期与时间函数【含辅助函数】

TODAY():获取当前日期。示例:如果系统日期是2005年9月10日则TODAY()等于2005-09-10。

DATEDELTA(date,deltadays):返回一个日期date后deltadays的日期。deltaDays可以为正值,负值,零。
示例:
DATEDELTA("2008-08-08",-10)等于2008-07-29。
DATEDELTA("2008-08-08",10)等于2008-08-18。

DATEINMONTH(date,number):函数返回在某一个月当中第几天的日期。
示例:
DATEINMONTH("2008-08-08",20)等于2008-08-20。
DATEINMONTH("2008-08-08",-1)等于2008-08-31。

DATEINWEEK(date,number):函数返回在某一个星期当中第几天的日期。
示例:
dateInWeek("2008-08-28",2)等于2008-08-26。
dateInWeek("2008-08-28",-1)等于2008-08-31。如果最后一个参数为-1,返回该日期所在星期的最后一天。

ENDOFMONTH(date,number)返回指定日期所在月份之前或之后月份的最后一天的日期值
date:指定日期,可缺省;缺省时默认为本月;
number:指定月份前/后月份的数量,整数,可缺省;缺省或者为0时,默认为date参数当月;正整数时,为date之后的月份,负整数时为date之前的月份;
备注:
不支持第一个参数缺省时第二个参数不缺省
示例:
ENDOFMONTH("2021-12-22")等于2021-12-31
ENDOFMONTH("2021-12-22",12)等于2022-12-31
ENDOFMONTH("2021-12-22",-12)等于2020-12-31
ENDOFMONTH("2021-12-22",36)等于2024-12-31

MONTH:(serial_number)返回日期中的月。月是介于1和12之间的一个数。
Serial_number:含有所求的月的日期.
备注:
FineReport将日期保存为系列数,一个系列数代表一个与之匹配的日期,以方便用户对日期进行数值式计算。
在1900年日期系统中,FineReport电子表格将1900年1月1日保存为系列数2,将1900年1月2日保存为系列数3,将1900年1月3日保存为系列数4……依此类推。如在1900年日期系统,1998年1月1日存为系列数35796。
示例:
MONTH("2000/1/1")等于1。
MONTH("2006/05/05")等于5。
MONTH("1997/04/20")等于4。
MONTH("2000-1-1","yyyy-MM-dd")等于1。
MONTH("2006-05-05","yyyy-MM-dd")等于5。
MONTH("1997-04-20","yyyy-MM-dd")等于4。
MONTH(35796)等于1。

MONTHDELTA(date,delta):返回指定日期date后delta个月的日期。
示例:
MONTHDELTA("2008-08-08",4)等于2008-12-08。

YEARDELTA(date,delta):返回指定日期后delta年的日期。
示例:YEARDELTA("2008-10-10",10)等于2018-10-10。

LEFT(text,num_chars):根据指定的字符数返回文本串中的第一个或前几个字符。
Text:包含需要选取字符的文本串或单元格引用。
Num_chars:指定返回的字符串长度。
备注:
Num_chars的值必须等于或大于0。如果num_chars大于整个文本的长度,LEFT函数将返回所有的文本。如果省略num_chars,则默认值为1。
示例:
LEFT("Fine software",8)等于“Fine sof”。
LEFT("Finesoftware")等于“F”。
如果单元格A3中含有“China”,则LEFT(A3,2)等于“Ch”。

STARTWITH(str1,str2):判断字符串str1是否以str2开始。
备注:
str1和str2都是大小写敏感的。
示例:
STARTWITH("FineReport","Fine")等于true。
STARTWITH("FineReport","Report")等于false。
STARTWITH("FineReport","fine")等于false。

SPLIT(String1,String2):返回由String2分割String1组成的字符串数组。
String1:以双引号表示的字符串。
String2:以双引号表示的分隔符。例如逗号","
示例:
SPLIT("hello,world,yes",",")=["hello","world","yes"]。
SPLIT("this is very good"," ") = ["this","is","very","good"]。
备注:
如果只有一个参数,则返回一个错误。如果有多个参数,则只有前两个起作用。

三、解决方案

3.1 常见的日期格式

注:将【-】替换成【/】等分隔符,公式使用方式基本相同,本文统一以【-】作列举。
YYYY-MM-DD:2024-11-25
YYYY-MM:2024-11
MM-DD:11-25
【MM-DD至MM-DD】:11-25至11-30
TT时:11时
TT:mm -> TT:mm:8:00 - 10:00
当日某时、当天两小时、当日、昨日、本周、上周、过去7天、周度、本月、上月、月度

3.2 常见的下钻动态传参格式化

注1:参数$$$动态改变,数据通常来自于图表组件的坐标轴。
注2:
本文中业务约定日期格式如下:
日: MM-DD
周: MM-DD至MM-DD
月: YYYY-MM

**将$$$分解为stime与etime并向下钻页面传递参数,日期格式化函数总结如下:**

1.时/当天两小时/当日
stime/etime: today()

2.日度 [MM-DD]->[YYYY-MM-DD]
stime/etime: left(today(),5)+$$$

3.昨日
stime/etime: DATEDELTA((left(today(),5)+$$$),-1)

4.过去7天 [考虑跨年] [含当日]
stime: DATEDELTA((left(today(),5)+$$$),-6)
etime: today()

5.本周/周度/上周 [参数形式为:MM-DD至MM-DD] [区间跨度为一周7天] [考虑跨年]
stime: 
1.基于$$$拼接
if((STARTWITH($$$,"12") && MONTH(today()) = 1),(year(today())-1)+'-'+left($$$,5),left(today(),5)+left($$$,5))
2.基于etime做减法
DATEDELTA(left(today(),5)+right($$$,5),-6)
etime: left(today(),5)+right($$$,5)

6.月度 [参数形式为:YYYY-MM]
stime: $$$+'-01'
etime: ENDOFMONTH($$$+'-01')

补充:从当日判断的常见日期范围
1. 当日: today()
2. 昨日: DATEDELTA(today(),-1)
3. 过去7天: DATEDELTA(today(),-6)
4. 本周:
[周一] DATEINWEEK(today(),1)
[周日] DATEINWEEK(today(),-1)
5. 上周:
[周一] DATEINWEEK(DATEDELTA(today(),-6),1)
[周日] DATEINWEEK(DATEDELTA(today(),-6),-1)
6.本月
[月初] DATEINMONTH(today(),1)
[月末] DATEINMONTH(today(),-1)
7.上月
[月初] MONTHDELTA(DATEINMONTH(today(),1),-1)
[月末] MONTHDELTA(DATEINMONTH(today(),-1),-1)

3.3 页面日期参数传递方式与交互逻辑

// 使用JS传参【日度:MM-DD、周度:MM-DD至MM-DD、月度:YYYY-MM】
// 可能的入参:日度[08-01]/周度[08-01至08-08]/月度[2024-08]
var flag = 0 // 判定标签
if(date.length<6) {
  flag = 1 // 日度
} else if (date.length<10) {
  flag = 3 // 月度
} else {
  flag = 2 // 周度
}
// 获取当前时间
var nowISO = new Date().toISOString()
// 获取当前年份
var currentYear = nowISO.split('-')[0]
// 获取当前月份
var currentMonth = nowISO.split('-')[1]
switch (flag) {
  case 1:
    // 日度处理方式
    if (currentMonth < date.split('-')[0] && date.split('-')[0] == 12) {
      // 跨年判断
      currentYear = currentYear - 1
    }
    var value = currentYear + '-' + date
    var startDate = value
    var endDate = value
break;
  case 2:
    // 周度处理方式
    var dates = date.split('至')
    // 跨年处理
    if ((dates[0].split('-')[0] > dates[1].split('-')[0]) && dates[0].split('-')[0] == 12) {
      var startDate = (currentYear - 1) + '-' + dates[0]
      var endDate = currentYear + '-' + dates[1]
    } else {
      var startDate = currentYear + '-' + dates[0]
      var endDate = currentYear + '-' + dates[1]
    }
    break;
  case 3:
    // 月度处理方式
    const big = ['01','03','05','07','08','10','12']
    // const small = [4,6,9,11]
    var year = date.split('-')[0]
    if ((year % 4 == 0 && year % 100 != 0) || year % 400 ==0) {
      var FebDays = '29'
    } else {
      var FebDays = '28'
    }
    var month = date.split('-')[1]
    if (month == 2) { // 2月
      var startDate = date + '-' + '01'
      var endDate = date + '-' + FebDays
    } else if (big.includes(month)) { // 大月
      var startDate = date + '-' + '01'
      var endDate = date + '-' + '31'
    } else { // 小月
      var startDate = date + '-' + '01'
      var endDate = date + '-' + '30'
    }
    break;
}

注:使用公式传参,参考上文公式,根据需求使用。


四、总结

本文总结了帆软提供的时间与日期处理函数的一些实用技巧,总结了一些页面参数传递方式与交互逻辑以供开发人员参考。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值