2つの日時, 経過時間の計算
Two Datetimes, Calculate Duration
日時Aから日時Bまでの経過時間を算出します。経過日数(例 “1.38日”)、経過時間数(例 “33.33時間”)、経過分数(例 “2000.00分”)、経過時間(例 “33:20″)のいずれか、もしくは複数を出力することが可能です。BがAよりも過去時刻の場合はマイナス符号が付与されます。
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
- two-datetimes-calculate-duration-2022.xml
- 2022-12-27 (C) Questetra, Inc. (MIT License)
(アドオン自動工程のインストールは Professional editionでのみ可能です)
Notes
- 案件(トークン)がこの自動工程に到達した際、「2つの時刻」が評価されます。
- たとえば「A:プロセス開始日時」「B:
#{#now}
」とセットすれば、自動工程までの所用時間が算出されます。
- たとえば「A:プロセス開始日時」「B:
- この自動工程では “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/
Capture


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式による文字列としての出力(データ設定式)
- └ R2271: EL式による日付日時としての出力(データ設定式)
- 固定的な設定