2つの日時, 経過時間の計算

2つの日時, 経過時間の計算

Two Datetimes, Calculate Duration

日時Aから日時Bまでの経過時間を算出します。経過日数(例 “1.38日”)、経過時間数(例 “33.33時間”)、経過分数(例 “2000.00分”)、経過時間(例 “33:20″)のいずれか、もしくは複数を出力することが可能です。BがAよりも過去時刻の場合はマイナス符号が付与されます。

Auto Step icon
Configs for this Auto Step
StrConfA
A: 日時(例 “2022-12-31 00:00″)をセットしてください *#{EL}
StrConfB
B: 日時(例 “2023-01-01 09:20″)をセットしてください *#{EL}
SelectConfC
C: 経過日数(Days)が格納される数値型データを選択してください (更新)
SelectConfD
D: 経過時間数(Hours)が格納される数値型データを選択してください (更新)
SelectConfE
E: 経過分数(Minutes)が格納される数値型データを選択してください (更新)
SelectConfF
F: 経過時間文字列(h:mm)が格納される文字列型データを選択してください (更新)
Script (click to open)
// GraalJS Script (engine type: 2)

//////// START "main()" /////////////////////////////////////////////////////////////////

main();
function main(){

//// == Config Retrieving / 工程コンフィグの参照 ==

const strTimeA          = configs.get      ( "StrConfA" );     /// REQUIRED
  if( strTimeA        === "" ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {A: String} is empty \n" );
  }
const strTimeB          = configs.get      ( "StrConfB" );     /// REQUIRED
  if( strTimeB        === "" ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {B: String} is empty \n" );
  }
const numPocketDays     = configs.getObject( "SelectConfC" );  // NotRequired
const numPocketHours    = configs.getObject( "SelectConfD" );  // NotRequired
const numPocketMinutes  = configs.getObject( "SelectConfE" );  // NotRequired
const strPocketTime     = configs.getObject( "SelectConfF" );  // NotRequired



//// == Data Retrieving / ワークフローデータの参照 ==
// (Nothing. Retrieved via Expression Language in Config Retrieving)



//// == Calculating / 演算 ==
const dateTimeA       = parseAsLocalDate ( strTimeA );
const dateTimeB       = parseAsLocalDate ( strTimeB );
const numMsecA        = dateTimeA.getTime();
const numMsecB        = dateTimeB.getTime();
const numMsecDuration = numMsecB - numMsecA;



//// == Data Updating / ワークフローデータへの代入 ==
if( numPocketDays !== null ){
  engine.setData ( numPocketDays,
    new java.math.BigDecimal( numMsecDuration /1000 /60 /60 /24 )
  );
}
if( numPocketHours !== null ){
  engine.setData ( numPocketHours,
    new java.math.BigDecimal( numMsecDuration /1000 /60 /60 )
  );
}
if( numPocketMinutes !== null ){
  engine.setData ( numPocketMinutes,
    new java.math.BigDecimal( numMsecDuration /1000 /60 )
  );
}
if( strPocketTime !== null ){
  let numPositiveIntM = Math.floor ( Math.abs ( ( numMsecDuration /1000 /60 ) ) );
  //  eg, 2000.00m -> 2000m,  -7.38m -> 7,  -67.38m -> 67
  let numH = Math.floor ( numPositiveIntM /60 );
  let numM = numPositiveIntM %60;
  if ( numMsecDuration < 0 ){
    engine.setData ( strPocketTime, '-' + numH + ":" + ( '0' + numM ).slice( -2 ) );
  }else{
    engine.setData ( strPocketTime,       numH + ":" + ( '0' + numM ).slice( -2 ) );
  }
}


} //////// END "main()" /////////////////////////////////////////////////////////////////


function parseAsLocalDate ( str ){ // strDateOrDatetime
  //
  // Searches a Date-or-Datetime String for YYYY, MM, DD, hh:mm in that order and
  //  returns JavaScript `Date` object.
  // Any format is forcibly recognized as LOCAL DATETIME. -- UNIQUE --
  // Supports "ISO 8601 format", "BPMS date format", "BPMS datetime format", etc,,,
  //
  // String "2022-12-31 23:59"          (Questetra BPMS datetime format)
  // ⇒ Date 2022-12-31T23:59:00+XX:00
  // String "2022-12-31 23:59:59"       (SQL Time format)
  // ⇒ Date 2022-12-31T23:59:00+XX:00
  // String "2022-12-31T23:59:59.999Z"  (ISO 8601 format)
  // ⇒ Date 2022-12-31T23:59:00+XX:00   // UNIQUE: Timezone not evaluated
  // String "2022-12-31"                (Questetra BPMS date format) 
  // ⇒ Date 2022-12-31T00:00:00+XX:00   // UNIQUE: not UTC
  // String "2022/12/31"                (Windows date-ja format)
  // ⇒ Date 2022-12-31T00:00:00+XX:00   // UNIQUE: not UTC
  // String "2022年12月31日"            (日本語/Japanese)
  // ⇒ Date 2022-12-31T00:00:00+XX:00
  //
  // String "20221231"
  // ⇒ Date 2022-12-31T00:00:00+XX:00   // UNIQUE: not UTC
  // String "20221231T235959Z"          (ISO 8601 format)
  // ⇒ Date 2022-12-31T23:59:00+XX:00   // UNIQUE: Timezone not evaluated
  // String "20221231T2359"
  // ⇒ Date 2022-12-31T23:59:00+XX:00

  if( str === "" ){
    throw new Error( "\n AutomatedTask ParseDateError:" +
                     " String is empty \n" );
  }
  const arrNumParts = str.match( /\d+/g );
  if( arrNumParts === null ){
    throw new Error( "\n AutomatedTask ParseDateError:" +
                     " No numeric characters in: " + str + "\n" );
  }

  /// function default
  let numYear    = 0; // limit in QBPMS: 1900 to 2100 (asof 2022-12)
  let indexMonth = 0;
  let numDay     = 0;
  let numHours   = 0;
  let numMinutes = 0;

  /// case: startsWith YYYYMMDD
  if( arrNumParts[0].length === 8 ){
    numYear      = parseInt( arrNumParts[0].slice( 0, 4 ), 10 );
    indexMonth   = parseInt( arrNumParts[0].slice( 4, 6 ), 10 ) - 1;
    numDay       = parseInt( arrNumParts[0].slice( 6, 8 ), 10 );
    if( arrNumParts.length > 1 ){ // "20221231T2359"
      numHours   = parseInt( arrNumParts[1].slice( 0, 2 ), 10 );
      numMinutes = parseInt( arrNumParts[1].slice( 2, 4 ), 10 );
    }

  /// case: not startsWith YYYYMMDD, like "2022-12-31 23:59"
  }else{
    if( arrNumParts.length < 3){
      throw new Error( "\n AutomatedTask ParseDateError:" +
                       " 3 Parts of numeric characters are needed in: " + str + "\n" );
    }
    numYear      = parseInt( arrNumParts[0], 10 );
    indexMonth   = parseInt( arrNumParts[1], 10 ) - 1;
    numDay       = parseInt( arrNumParts[2], 10 );
    if( arrNumParts.length > 4){
      numHours   = parseInt( arrNumParts[3], 10 );
      numMinutes = parseInt( arrNumParts[4], 10 );
    }
  }

  /// return JavaScript `Date` object
  return new Date( numYear, indexMonth, numDay, numHours, numMinutes );
}



/*
Notes:
- When the process reaches the automated step, the "Two Datetimes" will be automatically evaluated.
    - If "A: Process start time" and "B:`#{#now}`", the elapsed time to this step will be calculated.
- This automatic process evaluates both "2022-12-31" and "2022-12-31 00:00" as local time.
    - On JST platform (+9), both are interpreted as "2022-12-30T15:00:00Z" (2022-12-31T00:00:00+09:00).
    - Even if in ISO 8601 format with time zone, it is still evaluated as local time.
    - https://support.questetra.com/addons/converter-date-or-datetime-string-to-workflow-datetime-2022/
- Datetime-A or Datetime-B can be set in various formats.
    - Fixed config
        - `2022-12-31 00:00`.
        - `2022-12-31 00:00`
        - `2022-12-31` (= `2022-12-31 00:00`)
        - `2022-12-31` (= `2022-12-31 00:00`)
    - Dynamic config (Referring to process data)
        - `#{#q_TimeOfBirth}`
            - (Fixed time)
        - `#{#q_LastDayOfFiscalYear} 18:00`
            - (DATE data + Fixed time)
        - `#{#q_BirthDay}`
            - (If only DATE is set, assumed to be 00:00.)
        - `#{#q_OrderReceivedTime.addMonths(1).getLastTimeInMonth().getFirstTimeInDate().addHours(7)}`
            - 7:00 AM of the last day of the month following the "Order Received Time".
        - `#{processInstanceStartDatetime}` (process start time)
        - `#{#now}` (token arrival time)
    - R2272: Output of Strings via EL syntax https://questetra.zendesk.com/hc/en-us/articles/360024292872-R2272
        - R2271: Output of Date and Datetime Data via EL syntax https://questetra.zendesk.com/hc/en-us/articles/360024292672-R2271

Notes (ja):
- 案件(トークン)がこの自動工程に到達した際、「2つの時刻」が評価されます。
    - たとえば「A:プロセス開始日時」「B:`#{#now}`」とセットすれば、自動工程までの所用時間が算出されます。
- この自動工程では "2022-12-31" も "2022-12-31 00:00" もローカルタイムとして評価します。UNIQUE
    - JST基盤(+9)の場合、どちらも "2022-12-30T15:00:00Z" (2022-12-31T00:00:00+09:00) と解釈されます。
    - 仮にタイムゾーンが記載された ISO 8601 形式であっても、ローカルタイムとして評価されます。
    - https://support.questetra.com/ja/addons/converter-date-or-datetime-string-to-workflow-datetime-2022/
- 様々な書式で「日時A・日時B」をセットできます。
    - 固定的な設定
        - `2022-12-31 00:00`
        - `2022/12/31 00:00`
        - `2022-12-31` (= `2022-12-31 00:00`)
        - `2022年12月31日` (= `2022-12-31 00:00`)
        - `20221231 235959` (= `2022-12-31 23:59`)
    - 動的な設定(プロセスデータ等を参照する設定)
        - `#{#q_TimeOfBirth}`
            - (Fixed time)
        - `#{#q_LastDayOfFiscalYear} 18:00`
            - (DATE data + Fixed time)
        - `#{#q_BirthDay}`
            - (If only DATE is set, assumed to be 00:00.)
        - `#{#q_OrderReceivedTime.addMonths(1).getLastTimeInMonth().getFirstTimeInDate().addHours(7)}`
            - DATETIME "受注時刻" の翌月の末日の朝7時
        - `#{processInstanceStartDatetime}` (プロセス開始日時)
        - `#{#now}` (トークンがこの自動工程に到達した時刻)
    - R2272: EL式による文字列としての出力(データ設定式) https://questetra.zendesk.com/hc/ja/articles/360024292872-R2272
        - └ R2271: EL式による日付日時としての出力(データ設定式) https://questetra.zendesk.com/hc/ja/articles/360024292672-R2271
*/

Download

warning 自由改変可能な JavaScript (ECMAScript) コードです。いかなる保証もありません。
(アドオン自動工程のインストールは Professional editionでのみ可能です)

Notes

  • 案件(トークン)がこの自動工程に到達した際、「2つの時刻」が評価されます。
    • たとえば「A:プロセス開始日時」「B:#{#now}」とセットすれば、自動工程までの所用時間が算出されます。
  • この自動工程では “2022-12-31” も “2022-12-31 00:00” もローカルタイムとして評価します。UNIQUE

Capture

日時Aから日時Bまでの経過時間を算出します。経過日数(例 "1.38日")、経過時間数(例 "33.33時間")、経過分数(例 "2000.00分")、経過時間(例 "33:20")のいずれか、もしくは複数を出力することが可能です。BがAよりも過去時刻の場合はマイナス符号が付与されます。

Appendix

  • 様々な書式で「日時A・日時B」をセットできます。
    • 固定的な設定
      • 2022-12-31 00:00
      • 2022/12/31 00:00
      • 2022-12-31 (= 2022-12-31 00:00)
      • 2022年12月31日 (= 2022-12-31 00:00)
      • 20221231 235959 (= 2022-12-31 23:59)
    • 動的な設定(プロセスデータ等を参照する設定)
      • #{#q_TimeOfBirth}
        • (Fixed time)
      • #{#q_LastDayOfFiscalYear} 18:00
        • (DATE data + Fixed time)
      • #{#q_BirthDay}
        • (If only DATE is set, assumed to be 00:00.)
      • #{#q_OrderReceivedTime.addMonths(1).getLastTimeInMonth() .getFirstTimeInDate().addHours(7)}
        • DATETIME “受注時刻” の翌月の末日の朝7時
      • #{processInstanceStartDatetime} (プロセス開始日時)
      • #{#now} (トークンがこの自動工程に到達した時刻)
    • R2272: EL式による文字列としての出力(データ設定式)

See Also

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

%d人のブロガーが「いいね」をつけました。