Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Find everything you need to get certified on Fabric—skills challenges, live sessions, exam prep, role guidance, and more. Get started

v-stephen-msft

计算除周末和节假日的两个日期之间的工作日

引言:

在许多情况下,您可能需要计算两个日期之间的工作日。本文将告诉您如何计算出确切的工作日天数(即不包括周末和节假日)。

示例数据:

 

事实表:

vstephenmsft_0-1724120780424.png

节假日表:

vstephenmsft_1-1724120802870.png

预期结果:

vstephenmsft_2-1724120862635.png

下面分享给大家两种解决方案:

第一种方案:使用DAX

在过去,当我们遇到此类问题时,通常需要创建一个日期连续的日历表,这有助于我们根据日期表过滤和计算预期数据。

不过,2022年7月Power BI的功能摘要 里提到的一项新的DAX功能使我们不需要再创建这样一个连续的日历表,而是可以直接调用函数 “NETWORKDAYS ”来计算工作日。

NETWORKDAYS 用于返回(含)两个日期之间的工作日整数。

语法:

 

NETWORKDAYS(<开始日期>, <结束日期>[, <周末>, <节假日>])


与 DATEDIFF 功能不同的是,你可以编辑参数来指定哪些天和多少天是周末。你还可以将列表中的日期指定为不被视为工作日的节假日。

 

必须使用函数 DATE 或其他表达式的结果来指定日期。如果开始日期和结束日期都是空的,那么输出值也是空的。

 

如果开始日期或结束日期为空,则空的开始日期或结束日期将被视为 Date (1899, 12, 30)。

 

样例:

 

除周末外的工作日 = NETWORKDAYS ('事实表(DAX)'[开始日期],'事实表(DAX)'[结束日期],1)

 

除周末和节假日外的工作日 = NETWORKDAYS ('事实表(DAX)'[开始日期],'事实表(DAX)'[结束日期],1,VALUES('节假日'[日期]))

 

结果:

vstephenmsft_3-1724120917811.png

第二种方案:使用Power Query

目前M 语法中没有类似于 “NETWORKDAYS ”的函数可以直接使用。不过,我们可以构建一个自定义函数来实现类似的目标。

 

详细步骤

1. 复制“节假日”表并将其转换为日期列表。

vstephenmsft_6-1724121120913.png

 

2.新建空白查询,并在 “高级编辑器 ”中粘贴以下代码,创建函数 “除周末外的工作日 ”和函数 “除周末和节假日外的工作日”。

除周末外的工作日:

(开始日期 as date,结束日期 as date) as number=> 

let 

    日期列表=List.Dates(开始日期,Number.From(结束日期-开始日期)+1,#duration(1,0,0,0)), 

    //创建日期系列 

    移除周末=List.Select(日期列表,each Date.DayOfWeek(_,Day.Monday)<5), 

    //移除周末 

    统计天数=List.Count(移除周末) 

    //统计天数 

in 

  统计天数 

除周末和节假日外的工作日:

(开始日期 as date, 结束日期 as date, 节假日列表 as list) as number=> 

let 

    日期列表=List.Dates(开始日期,Number.From(结束日期-开始日期)+1,#duration(1,0,0,0)), 

    //创建日期系列 

    移除周末=List.Select(日期列表,each Date.DayOfWeek(_,Day.Monday)<5), 

    //移除周末 

    移除节假日=List.RemoveItems(移除周末, 节假日列表), 

    //移除节假日 

    统计天数=List.Count(移除节假日) 

    //统计天数 

in 

  统计天数 

List.Dates : 返回指定大小的日期值列表。 

Number.From: 从给定值返回值。这里我们用它来获取开始日期和结束日期之间的时间间隔,这对于生成日期列表非常方便。 

Date.DayOfWeek:返回一个数字(从 0 到 6): 返回一个数字(从 0 到 6),表示所提供日期时间的星期几。在这里,我们用它来确定是否是工作日(不包括周末)。 

List.Select : 从符合选择条件的列表中返回一个值列表。这里我们使用它来提取给定日期列表中的所有工作日(不包括周末)。 

List.RemoveItems :从 list1 中移除 list2 中所有给定值。在此,我们将从指定列表中删除 “节假日列表”中的所有值。 

List.Count :列表计数,返回列表中的项目数。 

3.创建两个自定义列,调用函数 “除周末外的工作日”和函数 “除周末和节假日外的工作日”。

vstephenmsft_7-1724121205819.pngvstephenmsft_8-1724121211880.png

完整的应用代码如下:

let 

    源 = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("Vc/BCcAwCAXQXTxHiFbbZpbg/mvUlJJ+wcvnKeqcpF2Vu2RR+4NRNDBF82oH2lnN0C4wY/FtvhagwVw23mAD7xys1TJ+Jr38sOLeJ++zEQ8=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [开始日期 = _t, 结束日期 = _t]), 

    更改的类型 = Table.TransformColumnTypes(源,{{"开始日期", type date}, {"结束日期", type date}}), 

    已添加自定义 = Table.AddColumn(更改的类型, "总天数", each Duration.Days([结束日期]-[开始日期])+1), 

    已添加自定义1 = Table.AddColumn(已添加自定义, "除周末外的工作日", each 除周末外的工作日([开始日期],[结束日期])), 

    已添加自定义2 = Table.AddColumn(已添加自定义1, "除周末和节假日外的工作日", each 除周末和节假日外的工作日([开始日期],[结束日期],节假日列表)) 

in 

    已添加自定义2 

希望本文能帮助你解决类似问题。

 

作者: 方毅雄

审阅者: Kerry Wang & Ula Huang

翻译:朱林慧