Skip to content
This repository was archived by the owner on Feb 22, 2024. It is now read-only.

Commit 112d172

Browse files
author
Aaron
authored
Merge pull request #1600 from anton-binary/datetime-blocks
Datetime blocks
2 parents a001a1e + 745cf92 commit 112d172

File tree

6 files changed

+156
-1
lines changed

6 files changed

+156
-1
lines changed

src/botPage/bot/Interface/ToolsInterface.js

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,78 @@
11
import CandleInterface from './CandleInterface';
22
import MiscInterface from './MiscInterface';
33
import IndicatorsInterface from './IndicatorsInterface';
4+
import { translate } from '../../../common/i18n';
45

56
// prettier-ignore
67
export default Interface => class extends IndicatorsInterface(
78
MiscInterface(CandleInterface(Interface))) {
89
getToolsInterface() {
910
return {
10-
getTime: () => parseInt(new Date().getTime() / 1000),
11+
getTime : () => parseInt(new Date().getTime() / 1000),
12+
toDateTime: (timestamp) => {
13+
const getTwoDigitValue = input => {
14+
if (input < 10) {
15+
return `0${input}`;
16+
}
17+
return `${input}`;
18+
}
19+
const invalidTimestamp = () => `${translate('Invalid timestamp')}: ${timestamp}`;
20+
if (typeof timestamp === 'number') {
21+
const dateTime = new Date(timestamp * 1000);
22+
if (dateTime.getTime()) {
23+
const year = dateTime.getFullYear();
24+
const month = getTwoDigitValue(dateTime.getMonth() + 1);
25+
const day = getTwoDigitValue(dateTime.getDate());
26+
const hours = getTwoDigitValue(dateTime.getHours());
27+
const minutes = getTwoDigitValue(dateTime.getMinutes());
28+
const seconds = getTwoDigitValue(dateTime.getSeconds());
29+
const formatGTMoffset = () => {
30+
const GMToffsetRaw = dateTime.getTimezoneOffset();
31+
const sign = GMToffsetRaw > 0 ? '-' : '+';
32+
const GMToffset = Math.abs(GMToffsetRaw);
33+
const h = Math.floor(GMToffset / 60);
34+
const m = GMToffset - h * 60;
35+
return `GMT${sign}${getTwoDigitValue(h)}${getTwoDigitValue(m)}`;
36+
}
37+
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds} ${formatGTMoffset()}`;
38+
}
39+
return invalidTimestamp();
40+
}
41+
return invalidTimestamp();
42+
},
43+
toTimestamp: (dateTimeString) => {
44+
const invalidDatetime = () => `${translate('Invalid date/time')}: ${dateTimeString}`;
45+
if (typeof dateTimeString === 'string') {
46+
const dateTime = dateTimeString
47+
.replace(/[^0-9.:-\s]/g, '')
48+
.replace(/\s+/g,' ')
49+
.trim()
50+
.split(' ');
51+
52+
const d = /^[12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
53+
const t = /^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9])(:([0-5][0-9])?)?$/;
54+
55+
let validatedDateTime;
56+
57+
if(dateTime.length >= 2) {
58+
validatedDateTime = d.test(dateTime[0]) && t.test(dateTime[1]) ? `${dateTime[0]}T${dateTime[1]}` : null;
59+
} else if(dateTime.length === 1) {
60+
validatedDateTime = d.test(dateTime[0]) ? dateTime[0] : null;
61+
} else {
62+
validatedDateTime = null;
63+
}
64+
65+
if(validatedDateTime) {
66+
const dateObj = new Date(validatedDateTime);
67+
// eslint-disable-next-line no-restricted-globals
68+
if(dateObj instanceof Date && !isNaN(dateObj)) {
69+
return dateObj.getTime() / 1000;
70+
}
71+
}
72+
return invalidDatetime();
73+
}
74+
return invalidDatetime();
75+
},
1176
...this.getCandleInterface(),
1277
...this.getMiscInterface(),
1378
...this.getIndicatorsInterface(),

src/botPage/bot/__tests__/block-tests/tools-test/Time.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,17 @@ describe('Time in tools', () => {
2727
expect(time2 - time1).most(3);
2828
});
2929
});
30+
31+
describe('Convert timestamp to date/time and back', () => {
32+
const timestamp = Math.ceil(new Date().getTime() / 1000);
33+
let result;
34+
beforeAll(done => {
35+
run(`(function() {return Bot.toTimestamp(Bot.toDateTime(${timestamp}));})()`).then(v => {
36+
result = v;
37+
done();
38+
});
39+
});
40+
it('converts timestamp to date/time string', () => {
41+
expect(result).satisfy(dt => dt === timestamp);
42+
});
43+
});
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
import './epoch';
22
import './timeout';
33
import './interval';
4+
import './todatetime';
5+
import './totimestamp';
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { translate } from '../../../../../../common/i18n';
2+
3+
Blockly.Blocks.todatetime = {
4+
init: function init() {
5+
this.appendDummyInput();
6+
this.appendValueInput('TIMESTAMP').appendField(translate('To Date/Time'));
7+
this.setInputsInline(true);
8+
this.setOutput(true, 'String');
9+
this.setColour('#dedede');
10+
this.setTooltip(
11+
translate(
12+
'Converts a number of seconds since Epoch into a string representing date and time. Example: 1546347825 will be converted to 2019-01-01 21:03:45.'
13+
)
14+
);
15+
},
16+
};
17+
18+
Blockly.JavaScript.todatetime = block => {
19+
const timestamp = Blockly.JavaScript.valueToCode(block, 'TIMESTAMP', Blockly.JavaScript.ORDER_ATOMIC);
20+
// eslint-disable-next-line no-underscore-dangle
21+
const functionName = Blockly.JavaScript.provideFunction_('timestampToDateString', [
22+
// eslint-disable-next-line no-underscore-dangle
23+
`function ${Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_}(timestamp) {
24+
return Bot.toDateTime(timestamp);
25+
}`,
26+
]);
27+
28+
const code = `${functionName}(${timestamp})`;
29+
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
30+
};
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { translate } from '../../../../../../common/i18n';
2+
3+
Blockly.Blocks.totimestamp = {
4+
init: function init() {
5+
this.appendDummyInput();
6+
this.appendValueInput('DATETIME').appendField(translate('To Timestamp'));
7+
this.setInputsInline(true);
8+
this.setOutput(true, 'Number');
9+
this.setColour('#dedede');
10+
this.setTooltip(
11+
translate(
12+
'Converts a string representing a date/time string into seconds since Epoch. Example: 2019-01-01 21:03:45 GMT+0800 will be converted to 1546347825. Time and time zone offset are optional.'
13+
)
14+
);
15+
},
16+
};
17+
18+
Blockly.JavaScript.totimestamp = block => {
19+
const dateString = Blockly.JavaScript.valueToCode(block, 'DATETIME', Blockly.JavaScript.ORDER_ATOMIC);
20+
// eslint-disable-next-line no-underscore-dangle
21+
const functionName = Blockly.JavaScript.provideFunction_('dateTimeStringToTimestamp', [
22+
// eslint-disable-next-line no-underscore-dangle
23+
`function ${Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_}(dateTimeString) {
24+
return Bot.toTimestamp(dateTimeString);
25+
}`,
26+
]);
27+
28+
const code = `${functionName}(${dateString})`;
29+
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
30+
};

static/xml/toolbox.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,20 @@
408408
<category name="Tools" i18n-text="Tools">
409409
<category name="Time" i18n-text="Time">
410410
<block type="epoch"></block>
411+
<block type="totimestamp">
412+
<value name="DATETIME">
413+
<shadow type="text">
414+
<field name="TEXT">yyyy-mm-dd hh:mm:ss</field>
415+
</shadow>
416+
</value>
417+
</block>
418+
<block type="todatetime">
419+
<value name="TIMESTAMP">
420+
<shadow type="math_number">
421+
<field name="NUM">0</field>
422+
</shadow>
423+
</value>
424+
</block>
411425
<block type="timeout">
412426
<value name="SECONDS">
413427
<shadow type="math_number">

0 commit comments

Comments
 (0)