- 动机
- TBEL语言指南
- 辅助函数
ThingsBoard在Rule Engine和Data Converters中支持用于数据处理的用户定义函数(UDF)。 UDF的原始编程语言为JavaScript,其流行、易用且简单,我们计划长期支持。 尽管如此,我们决定提供JavaScript的替代方案。
动机
ThingsBoard使用Java编写,目前采用Java 17。ThingsBoard中执行JS函数有两种方式:
一般来说,使用基于Node.js的远程JS Executor微服务,为ThingsBoard集群/微服务模式下的默认方式。
另一方面,使用由Nashorn JS引擎驱动的本地JS Executor,在JVM内运行,为ThingsBoard单体部署模式下的默认方式。
Nashorn JS引擎现已废弃,并从Java 16中移除,且执行较慢。有用户称Nashorn为平台的”软肋”。 因此我们需为其寻找替代方案。 许多用户建议使用GraalVM的内置多语言特性,但出于多方面的原因不适合我们。 主要原因包括安全及对UDF执行各环节的控制能力。 此外,大多数UDF是较简单的数据转换或过滤函数,我们希望对其实行更高效地执行。
对既有脚本/表达式语言(EL)实现的调研将我们引向MVEL。 ThingsBoard Expression Language(TBEL)本质上是MVEL的fork,增加了重要安全约束、 内置内存管理及ThingsBoard常用的辅助函数。
TBEL与Nashorn
TBEL更轻量且相比Nashorn执行更快。例如,执行1000个简单脚本(如 return msg.temperature > 20):
Nashorn需16秒,MVEL仅12毫秒,快超过1000倍。
我们对TBEL代码库进行了fork并增加了安全改进,以避免CPU或内存滥用。
因此无需在沙箱环境中运行Nashorn。
TBEL虽不及JS灵活,但大多数场景无需此能力。
需要JS灵活性的用户可以照常使用远程JS Executors。
TBEL与JS Executors
JS Executors为基于Node.js的独立微服务。
其功能强大并支持最新JS语言标准。 但远程执行JS函数有明显开销。 Rule Engine与JS executors通过队列通信。 该过程消耗资源并引入数毫秒级延迟。 若Rule Chain中存在多个Rule Node串联,此延迟可能成为问题。
TBEL执行资源消耗更少,且无跨进程通信的额外延迟。
TBEL语言指南
TBEL用于求值以Java语法编写的表达式。但与Java不同,TBEL为动态类型(支持可选类型),源码无需类型限定。 TBEL表达式可以简单到单个标识符,也可以复杂到包含方法调用和内联集合。
循环和条件的语法约束
在TBEL(ThingsBoard Expression Language)中,为保障脚本环境的兼容性与可靠性,存在若干语法限制。使用 foreach 替代传统 for 循环;在无显式 if 语句时,需将 ternary (? :) expressions 用括号包裹。
✅ 允许:
1
2
3
foreach (ValueType value : map) {
// Process each value
}
❌ Not allowed:
1
2
3
for (ValueType value : map) {
// Process each value
}
✅ 正确:
1
2
3
var msgNew = {
keyNew: (msg.humidity > 50 ? 3 : 0) // if (msg.humidity > 50) == true, result msgNew = { keyNew: : 3 }
};
❌ 错误:
1
2
3
var msgNew = {
keyNew: msg.humidity > 50 ? 3 : 0 // result msgNew = { 3 : 0 }
};
简单属性表达式
1
msg.temperature
此表达式中仅为单个标识符(msg.temperature),在TBEL中称为property expression, 其作用是从变量或上下文对象中提取属性。
TBEL也可用于求值布尔表达式。 若在Rule Engine中使用TBEL定义简单filter node脚本:
1
return msg.temperature > 10;
与Java一样,TBEL支持完整的运算符优先级规则,包括使用括号控制执行顺序。
1
return (msg.temperature > 10 && msg.temperature < 20) || (msg.humidity > 10 && msg.humidity < 60);
多语句
可使用分号分隔多条语句。除仅有一条语句或脚本最后一条语句外,均需以分号结束。
1
2
3
var a = 2;
var b = 2;
return a + b
注意 ‘a + b’ 后无分号。在MVEL中,换行不能替代分号。
类型强制转换
1
"123" == 123;
此表达式在TBEL中为 true,因为类型强制系统会将无类型数字 123 强制为String以进行比较。
映射
TBEL允许创建Map。我们使用自有Map实现以控制内存使用。 因此TBEL仅支持内联创建map。
1
2
// 创建新map
var map = {"temperature": 42, "nested" : "508"};
遍历map有两种写法:
- 显式entrySet()迭代:
1
2
3
4
5
6
7
8
9
10
11
12
13
// 遍历map
foreach(element : map.entrySet()){
// 获取key
element.getKey();
// 或
element.key;
// 获取value
element.getValue();
// 或
element.value;
}
- 不使用entrySet()的隐式迭代:
1
2
3
4
// 不使用entrySet() 遍历map
foreach (ValueType value : map) {
// 处理每个value
}
Map的常见操作:
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 修改key 的value
map.temperature = 0;
// 检查key 是否存在
if(map.temperature != null){
// <you code>
}
// 使用 ? 的Null-Safe 表达式
if(map.?nonExistingKey.smth > 10){
// <you code>
}
// get Info
var size = map.size(); // return 2
var memorySize = map.memorySize(); // return 24
map.humidity = 73; // return nothing => map = {"temperature": 0, "nested": "508", "humidity": 73}
map.put("humidity", 73); // return nothing => map ={"temperature": 0, "nested": "508", "humidity": 73}
map.putIfAbsent("temperature1", 73); // return nothing => map = {"temperature": 0, "nested": "508", "humidity": 73, "temperature1": 73}
// 修改value
map.temperature = 73; // return nothing => map = {"temperature": 73, "nested": "508", "humidity": 73, "temperature1": 73}
var put1 = map.put("temperature", 73); // return put1 = 73 => map = {"temperature": 73, "nested": "508", "humidity": 73, "temperature1": 73}
var putIfAbsent1 = map.putIfAbsent("temperature", 73); // return putIfAbsent1 = 73 => map = {"temperature": 73, "nested": "508", "humidity": 73, "temperature1": 73}
var replace = map.replace("temperature", 56); // return 73 => map = {"temperature": 56, "nested": "508", "humidity": 73, "temperature1": 73}
var replace1 = map.replace("temperature", 56, 42); // return true => map = {"temperature": 42, "nested": "508", "humidity": 73, "temperature1": 73}
var replace3 = map.replace("temperature", 48, 56); // return false => map = {"temperature": 42, "nested": "508", "humidity": 73, "temperature1": 73}
// remove Entry from the map by key
map.remove("temperature"); // return nothing => map = {"nested": "508", "humidity": 73, "temperature1": 73}
// get Keys/Values
var keys = map.keys(); // return ["nested", "humidity", "temperature1"]
var values = map.values(); // return ["508", 73, 73]
// sort
map.sortByKey(); // return nothing => map = {"humidity": 73, "nested": "508", "temperature1": 73}
var sortByValue = map.sortByValue(); // return nothing => map = {"humidity": 73, "temperature1": 73, "nested": "508"}
// add new Entry/(new key/new value)
var mapAdd = {"test": 12, "input" : {"http": 130}};
map.putAll(mapAdd);
// isMap(Object obj): checks if the given object is an instance of Map
isMap(mapAdd); // return true
Map - 不可修改
TBEL使用自有的不可修改Map实现。
示例:
1
2
3
4
5
var original = {};
original.humidity = 73;
var unmodifiable = original.toUnmodifiable(); // Create an ExecutionHashMap that is unmodifiable.
unmodifiable.put("temperature1", 96);
return unmodifiable; // An error occurs with the message: 'Error: unmodifiable.put("temperature1", 96): Map is unmodifiable'."
列表
TBEL允许创建List。我们使用自有List实现以控制脚本内存使用。 因此TBEL仅支持内联创建list。例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 创建新list
var list = ["A", "B", "C"];
// List 元素访问
list[0];
// list 大小
list.size();
// Foreach
foreach (item : list) {
var smth = item;
}
// for 循环
for (var i =0; i < list.size; i++) {
var smth = list[i];
}
在我们自有的列表实现中,Tbel库使用了大部分标准JavaScript方法,参见JavaScript Array。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
var list = ["A", "B", "C", "B", "C", "hello", 34567];
var listAdd = ["thigsboard", 4, 67];
// add/push
var addAll = list.addAll(listAdd); // return true => list = ["A", "B", "C", "B", "C", "hello", 34567, "thigsboard", 4, 67]
var addAllI = list.addAll(2, listAdd); // return true => list = ["A", "B", "thigsboard", 4, 67, "C", "B", "C", "hello", 34567, "thigsboard", 4, 67]
var add = list.add(3, "thigsboard"); // return nothing => list = ["A", "B", "thigsboard", "thigsboard", 4, 67, "C", "B", "C", "hello", 34567, "thigsboard", 4, 67]
var push = list.push("thigsboard"); // return true => list = ["A", "B", "thigsboard", "thigsboard", 4, 67, "C", "B", "C", "hello", 34567, "thigsboard", 4, 67, "thigsboard"]
var unshift = list.unshift("r"); // return nothing => list = ["r", "A", "B", "thigsboard", "thigsboard", 4, 67, "C", "B", "C", "hello", 34567, "thigsboard", 4, 67, "thigsboard"]
var unshiftQ = ["Q", 4];
var unshiftQun = list.unshift(unshift); // return nothing => list = [[["Q", 4], "r", "B", "thigsboard", "thigsboard", 4, 67, "C", "B", "C", "hello", 34567, "thigsboard", 4, 67, "thigsboard"]
// delete
var removeIndex2 = list.remove(2); // return "A" => list = [["Q", 4], "r", "B", "thigsboard", "thigsboard", 4, 67, "C", "B", "C", "hello", 34567, "thigsboard", 4, 67, "thigsboard"]
var removeValueC = list.remove("C"); // return true => list = [["Q", 4], "r", "B", "thigsboard", "thigsboard", 4, 67, "B", "C", "hello", 34567, "thigsboard", 4, 67, "thigsboard"]
var shift = list.shift(); // return ["Q", 4] => list = ["r", "B", "thigsboard", "thigsboard", 4, 67, "B", "C", "hello", 34567, "thigsboard", 4, 67, "thigsboard"]
var pop = list.pop(); // return "thigsboard" => list = ["r", "B", "thigsboard", "thigsboard", 4, 67, "B", "C", "hello", 34567, "thigsboard", 4, 67]
var splice3 = list.splice(3); // return ["thigsboard", 4, 67, "B", "C", "hello", 34567, "thigsboard", 4, 67] => list = ["r", "B", "thigsboard"]
var splice2 = list.splice(2, 2); // return ["thigsboard"] => list = ["r", "B"]
var splice1_4 = list.splice(1, 4, "start", 5, "end"); // return ["B"] => list = ["r", "start", 5, "end"]
// change
var set = list.set(3, "65"); // return "end"" => list = ["r", "start", 5, "65"]
list[1] = "98"; // return nothing => list = ["r", "98", 5, "65"]
list[0] = 2096; // return nothing => list = [2096, "98", 5, "65"]
list.sort(); // return nothing => list = [5, "65", "98", 2096] (sort Asc)
list.sort(true); // return nothing => list = [5, "65", "98", 2096] (sort Asc)
list.sort(false); // return nothing => list = [2096, "98", "65", 5] (sort Desc)
list.reverse(); // return nothing => list = [5, "65", "98", 2096]
var fill = list.fill(67); // return new List [67, 67, 67, 67] => list = [67, 67, 67, 67]
var fill4 = list.fill(4, 1); // return new List [67, 4, 4, 4] => list = [67, 4, 4, 4]
var fill4_6 = list.fill(2, 1, 4); // return new List [67, 2, 2, 2] => list = [67, 2, 2, 2]
// return new List/new String
var toSorted = list.toSorted(); // return new List [2, 2, 2, 67] (sort Asc)
var toSorted_true = list.toSorted(true); // return new List [2, 2, 2, 67] (sort Asc)
var toSorted_false = list.toSorted(false); // return new List [67, 2, 2, 2] (sort Desc)
var toReversed = list.toReversed(); // return new List [2, 2, 2, 67]
var slice = list.slice(); // return new List [67, 2, 2, 2]
var slice4 = list.slice(3); // return new List [2]
var slice1_5 = list.slice(0,2); // return new List [67, 2]
var with1 = list.with(1, 69); // return new List [67, 69, 2, 2, 2] => list = [67, 2, 2, 2]
var concat = list.concat(listAdd); // return new List [67, 2, 2, 2, "thigsboard", 4, 67] => list = [67, 2, 2, 2]
var join = list.join(); // return new String "67,2,2,2" => list = [67, 2, 2, 2]
var toSpliced2 = list.toSpliced(1, 0, "Feb"); // return new List [67, "Feb", 2, 2, 2] => list = [67, 2, 2, 2]
var toSpliced0_2 = list.toSpliced(0, 2); // return new List [2, 2] => list = [67, 2, 2, 2]
var toSpliced2_2 = list.toSpliced(2, 2); // return new List [67, 2] => list = [67, 2, 2, 2]
var toSpliced4_5 = list.toSpliced(2, 4, "start", 5, "end"); // return new List[67, 2, "start", 5, "end"] => list = [67, 2, 2, 2]
// get Info
var length = list.length(); // return 4
var memorySize = list.memorySize(); // return 32L
var indOf1 = list.indexOf("B", 1); // return -1
var indOf2 = list.indexOf(2, 2); // return 2
var sNumber = list.validateClazzInArrayIsOnlyNumber(); // return true
// isList(Object obj): checks if the given object is an instance of List
isList(list); // return true
列表 - 不可修改
TBEL使用自有的不可修改列表实现。
示例:
1
2
3
4
5
var original = [];
original.add(0x67);
var unmodifiable = original.toUnmodifiable(); // Create an ExecutionArrayList that is unmodifiable.
unmodifiable.add(0x35);
return unmodifiable; // An error occurs with the message: 'Error: unmodifiable.add(0x35): List is unmodifiable'."
集合
TBEL允许你创建集合。我们使用自己的集合实现以控制脚本的内存使用。 因此TBEL仅允许以内联方式创建集合。
在TBEL中,创建ExecutionLinkedHashSet有两种方式:
- 使用Map的entrySet()。可以直接从Map获取键值对集合:
1
2
3
4
5
var list = ["B", "A", "C", "A"];
var originalMap = {};
var set1 = originalMap.entrySet(); // create new Set from map, Empty
var set2 = set1.clone(); // clone new Set, Empty
var result1 = set1.addAll(list); // addAll list, no sort, size = 3 ("A" - duplicate), result = true
- 使用toSet(List list)方法。可以调用内置newSet()将List转为Set:
1
2
3
var list = ["B", "A", "C", "A"];
var set1 = toSet(list); // create new Set from newSet() with list, no sort, size = 3 ("A" - duplicate)
var set2 = newSet(); // create new Set from newSet(), Empty
- 支持的方法
| Method | 说明 |
|---|---|
add(value) |
向集合添加一个值 |
remove(value) |
从集合移除指定值 |
clear() |
移除所有元素 |
contains(value) |
检查集合中是否包含指定值 |
size() |
返回元素数量 |
toList() |
将集合转换为 List |
sort() |
按升序排序集合(原集合被修改) |
sort(boolean asc) |
按升序或降序就地排序 |
toSorted() |
返回升序排序的新列表(原集合不变) |
toSorted(boolean asc) |
返回按指定顺序排序的新列表 |
示例:
- Foreach and For-Loop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Create a new set with value
var set = createSet(["A", "B", "C"]);
var set2 = toSet(msg.list); // create new from list, size = 3
var set2_0 = set2.toArray()[0]; // return "A", value with index = 0 from Set
var set2Size = set2.size(); // return size = 3
var smthForeach = "";
foreach (item : set2) { // foreach for Set
smthForeach += item; // return "ABC"
}
var smthForLoop= "";
var set2Array = set2.toArray(); // for loop for Set (Set to array))
for (var i =0; i < set2.size; i++) {
smthForLoop += set2Array[i]; // return "ABC"
}
- Add/Remove
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// add
var list = ["B", "C", "A", "B", "C", "hello", 34567];
var setAdd = toSet(["thigsboard", 4, 67]); // create new, size = 3
var setAdd1_value = setAdd.clone(); // clone setAdd, size = 3
var setAdd2_result = setAdd.add(35); // add value = 35, result = true
var setAdd2_value = setAdd.clone(); // clone setAdd (fixing the result add = 35), size = 4
var setAddList1 = toSet(list); // create new from list without duplicate value ("B" and "C" - only one), size = 5
var setAdd3_result = setAdd.addAll(setAddList1); // add all without duplicate values, result = true
var setAdd3_value = setAdd.clone(); // clone setAdd (with addAll), size = 9
var setAdd4_result = setAdd.add(35); // add duplicate value = 35, result = false
var setAdd4_value = setAdd.clone(); // clone setAdd (after add duplicate value = 35), size = 9
var setAddList2 = toSet(list); // create new from list without duplicate value ("B" and "C" - only one), start: size = 5, finish: size = 7
var setAdd5_result1 = setAddList2.add(72); // add is not duplicate value = 72, result = true
var setAdd5_result2 = setAddList2.add(72); // add duplicate value = 72, result = false
var setAdd5_result3 = setAddList2.add("hello25"); // add is not duplicate value = "hello25", result = true
// addAll
var setAdd5_value = setAddList2.clone(); // clone setAddList2, size = 7
var setAdd6_result = setAdd.addAll(setAddList2); // add all with duplicate values, result = true
var setAdd6_value = setAdd.clone(); // clone setAdd (after addAll setAddList2), before size = 9, after size = 11, added only is not duplicate values {"hello25", 72}
// remove
var setAdd7_value = setAdd6_value.clone(); // clone setAdd6_value, before size = 11, after remove value = 4 size = 10
var setAdd7_result = setAdd7_value.remove(4); // remove value = 4, result = true
var setAdd8_value = setAdd7_value.clone(); // clone setAdd7_value, before size = 10, after clear size = 0
setAdd8_value.clear(); // setAdd8_value clear, result size = 0
- sort/toSorted
1
2
3
4
5
6
7
8
9
10
11
var list = ["C", "B", "A", 34567, "B", "C", "hello", 34];
var set1 = toSet(list); // create new from method toSet(List list) no sort, size = 6 ("A" and "C" is duplicated)
var set2 = toSet(list); // create new from method toSet(List list) no sort, size = 6 ("A" and "C" is duplicated)
var set1_asc = set1.clone(); // clone set1, size = 6
var set1_desc = set1.clone(); // clone set1, size = 6
set1.sort(); // sort set1 -> asc
set1_asc.sort(true); // sort set1_asc -> asc
set1_desc.sort(false); // sort set1_desc -> desc
var set3 = set2.toSorted(); // toSorted set3 -> asc new Set
var set3_asc = set2.toSorted(true); // toSorted set3 -> asc new Set
var set3_desc = set2.toSorted(false); // toSorted set3 -> desc new Set
- contains/toList/isSet
1
2
3
4
5
6
7
var list = ["C", "B", "A", 34567, "B", "C", "hello", 34];
var set1 = toSet(list); // create new from method toSet(List list) no sort, size = 6 ("A" and "C" is duplicated)
var result1 = set1.contains("A"); // return true
var result2 = set1.contains("H"); // return false
var tolist = set1.toList(); // create new List from Set, size = 6
var result3 = isSet(set1); // rerturn true
var result4 = isSet(tolist); // rerturn false
集合 - 不可修改
TBEL使用自有的不可修改集合实现。
示例:
1
2
3
4
5
var original = createSet();
original.add(0x67);
var unmodifiable = original.toUnmodifiable(); // Create an ExecutionArrayList that is unmodifiable.
unmodifiable.add(0x35);
return unmodifiable; // An error occurs with the message: 'Error: unmodifiable.add(0x35): set is unmodifiable'."
数组
TBEL允许你创建数组。为了控制内存使用,我们仅允许原始类型的数组。(字符串数组会自动转换为列表。)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Create new array
var array = new int[3];
array[0] = 1;
array[1] = 2;
array[2] = 3;
var str = "My String";
var str0 = str[0]; // returns 'M';
function sum(list){
var result = 0;
for(var i = 0; i < list.length; i++){
result += list[i];
}
return result;
};
var sum = sum(array); // returns 6
// isArray(Object obj): checks if the given object is an array
isArray(array); // return true
1
2
3
4
5
6
7
// Will cause ArrayIndexOutOfBoundsException.
var array = new int[3];
array[0] = 1;
array[1] = 2;
array[2] = 3;
array[3] = 4; return: Error with message:"Invalid statement: 4" and "[Line: 5, Column: 12]"
Avoid i++ inside […]:
✅ Allowed:
1
2
var channel_id = input[i];
i = i + 1;
❌ Not allowed:
1
var channel_id = input[(i++)];
字面量
字面量用于在脚本源码中表示固定值。
字符串字面量
字符串字面量可用单引号或双引号表示。
1
2
"This is a string literal"
'This is also string literal'
字符串转义序列:
- \ - 双重转义,允许在字符串中渲染单个反斜杠。
- \n - 换行符
- \r - 回车符
- \u#### - Unicode字符(例如:\uAE00)
- ### - 八进制字符(例如:\73)
数值字面量
整数可用十进制(base 10)、八进制(base 8)或十六进制(base 16)表示。
十进制整数为不以0开头的任意数字。
1
125 // decimal
八进制整数以0开头,后跟0–7的数字。
1
0353 // octal
十六进制以0x开头,后跟0-9或A-F。
1
0xAFF0 // hex
浮点数由整数部分和点号表示的小数部分组成,可有可选的类型后缀。
1
2
3
10.503 // double
94.92d // double
14.5f // float
*BigInteger* 和 *BigDecimal* 字面量可使用后缀 B 和 I(必须大写)。
1
2
104.39484B // BigDecimal
8.4I // BigInteger
布尔字面量由保留关键字 true 和 false 表示。
null字面量由保留关键字 null 或 nil 表示。
使用Java类
TBEL实现允许使用 java.util 和 java.lang 包中的部分 Java类。例如:
1
var foo = Math.sqrt(4);
数字转十六进制/八进制/二进制字符串
- Byte
1
2
3
4
var b16 = Integer.toString(0x1A, 16); // Hexadecimal "1a"
var b10 = Integer.toString(0x1A, 10); // Decimal "26"
var b8 = Integer.toString(0x1A, 8); // Octal "32"
var b2 = Integer.toString(0x1A, 2); // Binary "11010"
- Integer
1
2
3
4
var i16 = Integer.toString(-255, 16); // Hexadecimal "-ff"
var i10 = Integer.toString(-255, 10); // Decimal "-255"
var i8 = Integer.toString(-255, 8); // Octal "-377"
var i2 = Integer.toString(-255, 2); // Binary "-11111111"
- Float
1
2
3
var f0 =7823764.8374;
var f16 = Float.toHexString(f0); // Hexadecimal "0x1.dd8654p22"
var f10 = f0.toString(); // Decimal "7823764.8374"
- Long
1
2
3
4
var l16 = Long.toString(9223372036854775807, 16); // Hexadecimal "7fffffffffffffff"
var l10 = Long.toString(9223372036854775807, 10); // Decimal "9223372036854775807"
var l8 = Long.toString(9223372036854775807, 8); // Octal "777777777777777777777"
var l2 = Long.toString(9223372036854775807, 2); // Binary "111111111111111111111111111111111111111111111111111111111111111"
- Double
1
2
3
var dd0 = 99993219.156013e-002;
var dd16 = Double.toHexString(dd0); // Hexadecimal "0x1.e83f862142b5bp19"
var dd10 = String.format("%.8f",dd0); // Decimal "999932,19156013"
出于安全考虑,这些类的使用受到限制。您可以调用静态和非静态方法,但不能将类的实例赋值给变量:
1
2
3
var list = ["A", "B", "C"];
java.util.Collections.reverse(list); // allowed
list = new java.util.ArrayList(); // Not allowed
为简化从JavaScript的迁移,我们引入了JSON类,提供JSON.stringify和JSON.parse静态方法,其功能与JavaScript中的对应方法类似。
例如:
1
2
var metadataStr = JSON.stringify(metadata);
var metadata = JSON.parse(metadataStr);
出于同样的目的:
- 添加了decodeToJson方法。
- 添加了Date类,无需指定包名即可使用。
- 在
tbel库中,map和list类对其主要方法进行了扩展支持,类似于Java。
流程控制
If-Then-Else
TBEL支持完整的C/Java风格if-then-else块。例如:
1
2
3
4
5
6
7
if (temperature > 0) {
return "Greater than zero!";
} else if (temperature == -1) {
return "Minus one!";
} else {
return "Something else!";
}
三元表达式
与Java一样支持三元表达式:
1
temperature > 0 ? "Yes" : "No";
支持嵌套三元表达式。
Foreach
TBEL最强大的特性之一为foreach运算符。其语法与Java 1.5的foreach相似。 它接受由冒号分隔的两个参数:第一个为当前元素的局部变量,第二个为要迭代的集合或数组。
例如:
1
2
3
4
5
var numbers = [1, 2, 3];
var sum = 0;
foreach (n : numbers) {
sum+=n;
}
由于TBEL将String视为可迭代对象,可使用foreach逐字符遍历String:
1
2
3
4
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
foreach (c : str) {
//do something
}
For循环
1
2
3
4
var sum = 0;
for (var i =0; i < 100; i++) {
sum += i;
}
Do While, Do Until
do while和do until在TBEL中已实现,遵循与Java相同的约定,其中until是while的反义。
1
2
3
4
do {
x = something();
}
while (x != null);
……在语义上等价于……
1
2
3
4
do {
x = something();
}
until (x == null);
While, Until
TBEL实现了标准的while循环,并额外增加了反义的until循环。
1
2
3
while (isTrue()) {
doSomething();
}
……或者……
1
2
3
until (isFalse()) {
doSomething();
}
辅助函数
btoa
从二进制字符串(即字符串中的每个字符被视为二进制数据的一个字节)创建Base64编码的ASCII字符串。
语法:
String btoa(String input)
参数:
- input:
string- 要编码的二进制字符串。
返回值:
返回表示输入内容Base64编码的ASCII字符串。
示例:
1
2
var encodedData = btoa("Hello, world"); // encode a string
var decodedData = atob(encodedData); // decode the string
atob
解码已使用Base64编码的数据字符串。
语法:
String atob(String input)
参数:
- input:
string- 包含Base64编码数据的二进制字符串。
返回值:
包含从encodedData解码数据的ASCII字符串。
示例:
1
2
var encodedData = btoa("Hello, world"); // encode a string
var decodedData = atob(encodedData); // decode the string
toFixed
将double值四舍五入到“最近邻”。
语法:
double toFixed(double value, int precision)
参数:
- value:
double- double值。 - precision:
int- 精度。
返回值:
四舍五入后的double值
示例:
1
2
return toFixed(0.345, 1); // returns 0.3
return toFixed(0.345, 2); // returns 0.35
toInt
将double值四舍五入到最接近的整数。
语法:
double toInt(double value)
参数:
- value:
double- double值。
返回值:
四舍五入后的整数值
示例:
1
2
3
return toInt(0.3); // returns 0
return toInt(0.5); // returns 1
return toInt(2.7); // returns 3
stringToBytes
将输入的二进制字符串转换为字节列表。
语法:
*List
参数:
- input:
Binary string- 字符串中的每个字符被视为二进制数据的一个字节。 - charsetName:
String- 可选的字符集名称,默认UTF-8。
返回值:
字节列表。
示例: 二进制字符串
1
2
3
4
5
6
7
8
var base64Str = "eyJoZWxsbyI6ICJ3b3JsZCJ9"; // Base 64 representation of the '{"hello": "world"}'
var bytesStr = atob(base64Str);
return stringToBytes(bytesStr); // Returns [123, 34, 104, 101, 108, 108, 111, 34, 58, 32, 34, 119, 111, 114, 108, 100, 34, 125]
var inputStr = "hello world";
return stringToBytes(inputStr); // Returns [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
var charsetStr = "UTF8";
return stringToBytes(inputStr, charsetStr); // Returns [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
示例: JSON字符串形式的Object
1
2
3
4
5
var dataMap = {};
dataMap.inputStr = "hello world";
var dataJsonStr = JSON.stringify(dataMap);
var dataJson = JSON.parse(dataJsonStr);
return stringToBytes(dataJson.inputStr); // Returns [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
bytesToString
从字节列表创建字符串。
语法:
*String bytesToString(List
参数:
- bytesList:
List of Bytes- 字节列表。 - charsetName:
String- 可选的字符集名称,默认UTF-8。
返回值:
从指定字节列表构造的字符串。
示例:
1
2
var bytes = [0x48,0x45,0x4C,0x4C,0x4F];
return bytesToString(bytes); // Returns "HELLO"
decodeToString
bytesToString的别名。
decodeToJson
将字节列表解码为JSON文档。
语法:
*String decodeToJson(List
参数:
- bytesList:
List of Bytes- 字节列表。
返回值:
JSON对象或基本类型。
示例:
1
2
3
4
var base64Str = "eyJoZWxsbyI6ICJ3b3JsZCJ9"; // Base 64 representation of the '{"hello": "world"}'
var bytesStr = atob(base64Str);
var bytes = stringToBytes(bytesStr);
return decodeToJson(bytes); // Returns '{"hello": "world"}'
isTypeInValue
isBinary
验证字符串是否表示二进制(base-2)值。
语法:
int isBinary(String str)
参数:
- str:
String- 要检查是否为二进制数的字符串。默认字符集为UTF-8。
返回值:
表示结果的整数值:
- 如果字符串是二进制则返回’2’。
- 如果字符串不是二进制则返回’-1’。
示例:
1
2
return isBinary("1100110"); // Returns 2
return isBinary("2100110"); // Returns -1
isOctal
验证字符串是否表示八进制(base-8)值。
语法:
int isOctal(String str)
参数:
- str:
String- 要检查是否为八进制数的字符串。默认字符集为UTF-8。
返回值:
表示结果的整数值:
- 如果字符串是八进制则返回’8’。
- 如果字符串不是八进制则返回’-1’。
示例:
1
2
return isOctal("4567734"); // Returns 8
return isOctal("8100110"); // Returns -1
isDecimal
验证字符串是否表示十进制(base-10)值。
语法:
int isDecimal(String str)
参数:
- str:
String- 要检查是否为十进制数的字符串。默认字符集为UTF-8。
返回值:
表示结果的整数值:
- 如果字符串是十进制则返回’10’。
- 如果字符串不是十进制则返回’-1’。
示例:
1
2
return isDecimal("4567039"); // Returns 10
return isDecimal("C100110"); // Returns -1
isHexadecimal
验证字符串是否表示十六进制(base-16)值。
语法:
int isHexadecimal(String str)
参数:
- str:
String- 要检查是否为十六进制数的字符串。默认字符集为UTF-8。
返回值:
表示结果的整数值:
- 如果字符串是十六进制则返回’16’。
- 如果字符串不是十六进制则返回’-1’。
示例:
1
2
return isHexadecimal("F5D7039"); // Returns 16
return isHexadecimal("K100110"); // Returns -1
isNaN
检查double值是否为”非数字”(NaN)。
语法:
boolean isNaN(double value)
参数:
- value:
double- 要检查是否为NaN的值。
返回值:
表示结果的布尔值:
- 如果值是NaN则返回
true。 - 如果值是有效数字则返回
false。
示例:
1
2
return isNaN(0.0 / 0.0); // Returns true
return isNaN(1.0); // Returns false
encodeDecodeUri
encodeURI
- encodeURI()对除以下字符外的所有字符进行转义:
1
A–Z a–z 0–9 - _ . ! ~ * ' ( ) ; / ? : @ & = + $ , #
语法:
String encodeURI(String uri)
参数:
- uri:
String- 要编码为URI的字符串。
返回值:
表示将提供的字符串编码为URI的新字符串。
示例:
1
2
var uriOriginal = "-_.!~*'();/?:@&=+$,#ht://example.ж д a/path with spaces/?param1=Київ 1¶m2=Україна2";
return encodeURI(uriOriginal); // Returns "-_.!~*'();/?:@&=+$,#ht://example.%D0%B6%20%D0%B4%20a/path%20with%20spaces/?param1=%D0%9A%D0%B8%D1%97%D0%B2%201¶m2=%D0%A3%D0%BA%D1%80%D0%B0%D1%97%D0%BD%D0%B02"
decodeURI
语法:
String decodeURI(String uri)
参数:
- uri:
String- 完整的已编码统一资源标识符。
返回值:
表示指定已编码统一资源标识符(URI)的未编码版本的新字符串。
示例:
1
2
var uriEncode = "-_.!~*'();/?:@&=+$,#ht://example.%D0%B6%20%D0%B4%20a/path%20with%20spaces/?param1=%D0%9A%D0%B8%D1%97%D0%B2%201¶m2=%D0%A3%D0%BA%D1%80%D0%B0%D1%97%D0%BD%D0%B02";
return decodeURI(uriEncode); // Returns "-_.!~*'();/?:@&=+$,#ht://example.ж д a/path with spaces/?param1=Київ 1¶m2=Україна2"
raiseError
语法:
void raiseError(String message)
参数:
- message:
String- 异常消息信息。
返回值:
带有msg = message的新RuntimeException。
示例:
1
2
3
4
5
var message = "frequency_weighting_type must be 0, 1 or 2.";
return raiseError(message); // Returns "frequency_weighting_type must be 0, 1 or 2."
var value = 4;
message = "frequency_weighting_type must be 0, 1 or 2. A value of " + value + " is invalid.";
return raiseError(message, value); // Returns "frequency_weighting_type must be 0, 1 or 2. A value of 4 is invalid."
printUnsignedBytes
将List <有符号byte>转换为List<无符号integer>。无符号integer>有符号byte>
语法:
*List
参数:
- byteArray:
List of byte- 字节值列表,其中每个整数代表一个字节。
返回值:
List
示例:
1
2
3
4
5
6
7
var hexStrBe = "D8FF"; // [-40, -1]
var listBe = hexToBytes(hexStrBe);
return printUnsignedBytes(listBe); // Returns [216, 255]
var hexStrLe = "FFD8"; // [-1, -40]
var listLe = hexToBytes(hexStrLe);
return printUnsignedBytes(listLe); // Returns [255, 216]
pad
padStart
- 用另一个字符串(必要时多次)填充此字符串,直到结果字符串达到给定长度。
- 填充从此字符串的开头开始应用。
语法:
String padEnd(String str, int targetLength, char padString)
参数:
- str:
String- 用给定字符串(必要时重复)填充此字符串。 - targetLength:
List of byte- 填充后结果字符串的长度。如果该值小于或等于str.length,则原样返回str。 - padString:
List of byte- 用于填充当前str的字符串。如果padString过长超出targetLength,将从末尾截断。
返回值:
String
示例:
1
2
3
4
5
6
7
8
var str = "010011";
return padStart(str, 8, '0'); // Returns "00010011"
var str ="1001010011";
return padStart(str, 8, '0'); // Returns "1001010011"
return padStart(str, 16, '*'); // Returns "******1001010011"
var fullNumber = "203439900FFCD5581";
var last4Digits = fullNumber.substring(11);
return padStart(last4Digits, fullNumber.length(), '*'); // Returns "***********CD5581"
padEnd
- 用给定字符串(必要时重复)填充此字符串,使结果字符串达到给定长度。
- 填充从此字符串的末尾开始应用。
语法:
String padEnd(String str, int targetLength, char padString)
参数:
- str:
String- 用给定字符串(必要时重复)填充此字符串。 - targetLength:
List of byte- 填充后结果字符串的长度。如果该值小于或等于str.length,则原样返回当前字符串。 - padString:
List of byte- 用于填充当前str的字符串。如果padString过长超出targetLength,将被截断:从左到右的语言取最左部分,从右到左的语言取最右部分。
返回值:
String
示例:
1
2
3
4
5
6
7
8
9
10
var str = "010011";
padEnd(str, 8, '0'); // Returns "01001100"
var str ="1001010011";
padEnd(str, 8, '0'); // Returns "1001010011"
padEnd(str, 16, '*'); // Returns "1001010011******"
var fullNumber = "203439900FFCD5581";
var last4Digits = fullNumber.substring(0, 11);
padEnd(last4Digits, fullNumber.length(), '*'); // Returns "203439900FF******"
numberToRadixString
intToHex
longToHex
floatToHex
doubleToHex
将输入数字(int、long、float、double)转换为十六进制字符串。
语法:
String intToHex(Integer i[, boolean bigEndian, boolean pref, int len]) String longToHex(Long l[, boolean bigEndian, boolean pref, int len]) String floatToHex(Float f[, boolean bigEndian]) String doubleToHex(Double d[, boolean bigEndian])
参数:
- i, l, f, d:
Number- 格式:Integer、Long、Float、Double。 - bigEndian:
boolean- 可选,为true时使用大端(BE)字节序,否则为小端(LE)。默认:true(BE)。 - pref:
boolean- 可选,以"0x"格式输出。默认:false。 - len:
int- 可选,要转换为文本的数字字节数。
返回值:
十六进制格式的字符串。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var i = 0x7FFFFFFF; // (2147483647);
intToHex(i, true, true); // Returns "0x7FFFFFFF"
intToHex(171, true, false); // Returns "AB"
intToHex(0xABCDEF, false, true, 4); // Returns "0xCDAB"
intToHex(0xABCD, false, false, 2); // Returns "AB"
longToHex(9223372036854775807, true, true); // Returns "0x7FFFFFFFFFFFFFFF"
longToHex(0x7A12BCD3, true, true, 4); // Returns "0xBCD3"
longToHex(0x7A12BCD3, false, false, 4); // Returns "127A"
floatToHex(123456789.00); // Returns "0x4CEB79A3"
floatToHex(123456789.00, false); // Returns "0xA379EB4C"
doubleToHex(1729.1729d); // Returns "0x409B04B10CB295EA"
doubleToHex(1729.1729d, false); // Returns "0xEA95B20CB1049B40"
intLongToRadixString
将输入数字(int、long)转换为指定进制字符串(默认十进制)。
语法:
String intLongToRadixString(Long number[, int radix, boolean bigEndian, boolean pref])
参数:
- number:
Number- 格式:Long。 - radix:
int- 可选,用于解析为字符串格式的进制(BinaryString、OctalString、DecimalString、HexDecimalString)。默认:DecimalString。 - bigEndian:
boolean- 可选,为true时使用大端(BE)字节序,否则为小端(LE)。默认:true(BE)。 - pref:
boolean- 可选,以"0x"格式输出。默认:false。
返回值:
BinaryString、OctalString、DecimalString、HexDecimalString格式的字符串。
示例:
1
2
3
4
5
6
7
8
9
intLongToRadixString(58, 2); // Returns "00111010"
intLongToRadixString(9223372036854775807, 2); // Returns "0111111111111111111111111111111111111111111111111111111111111111"
intLongToRadixString(13158, 8); // Returns "31546"
intLongToRadixString(-13158, 8); // Returns "1777777777777777746232"
intLongToRadixString(-13158, 10); // Returns "-13158"
intLongToRadixString(13158, 16); // Returns "3366"
intLongToRadixString(-13158, 16); // Returns "FFCC9A"
intLongToRadixString(9223372036854775807, 16); // Returns "7FFFFFFFFFFFFFFF"
intLongToRadixString(-13158, 16, true, true); // Returns "0xFFCC9A"
parseHex
parseHexToInt
将十六进制字符串转换为整数。
语法:
int parseHexToInt(String hex[, boolean bigEndian])
参数:
- hex:
string- 大端字节序的十六进制字符串。 - bigEndian:
boolean- 可选,为true时使用大端(BE)字节序,否则为小端(LE)。
返回值:
解析后的整数值。
示例:
1
2
3
4
parseHexToInt("BBAA"); // Returns 48042
parseHexToInt("BBAA", true); // Returns 48042
parseHexToInt("AABB", false); // Returns 48042
parseHexToInt("BBAA", false); // Returns 43707
parseLittleEndianHexToInt
[parseHexToInt(hex, false)]的别名(#parsehextoint)
语法:
int parseLittleEndianHexToInt(String hex)
parseBigEndianHexToInt
[parseHexToInt(hex, true)]的别名(#parsehextoint)
语法:
int parseBigEndianHexToInt(String hex)
parseHexToFloat
将十六进制字符串转换为浮点数。
语法:
Float parseHexToFloat(String hex[, boolean bigEndian])
参数:
- hex:
string- 大端字节序的十六进制字符串。 - bigEndian:
boolean- 可选,为true时使用大端(BE)字节序,否则为小端(LE)。
返回值:
解析后的浮点值。
示例:
1
2
3
4
parseHexToFloat("41EA62CC"); // Returns 29.29824f
parseHexToFloat("41EA62CC", true); // Returns 29.29824f
parseHexToFloat("41EA62CC", false); // Returns -5.948442E7f
parseHexToFloat("CC62EA41", false); // Returns 29.29824f
parseLittleEndianHexToFloat
[parseHexToFloat(hex, false)]的别名(#parsehextofloat)
语法:
float parseLittleEndianHexToFloat(String hex)
parseBigEndianHexToFloat
[parseBigEndianHexToFloat(hex, true)]的别名(#parsehextofloat)
语法:
float parseBigEndianHexToFloat(String hex)
parseHexIntLongToFloat
将十六进制字符串转换为浮点数。
语法:
Float parseHexIntLongToFloat(String hex, boolean bigEndian)
参数:
- hex:
string- 大端字节序的十六进制字符串。 - bigEndian:
boolean- 为true时使用大端(BE)字节序,否则为小端(LE)。
返回值:
解析后的浮点值。
示例:
1
2
3
4
5
6
return parseHexIntLongToFloat("0x0A", true); // Returns 10.0f
return parseHexIntLongToFloat("0x0A", false); // Returns 10.0f
return parseHexIntLongToFloat("0x00000A", true); // Returns 10.0f
return parseHexIntLongToFloat("0x0A0000", false); // Returns 10.0f
return parseHexIntLongToFloat("0x000A0A", true); // Returns 2570.0f
return parseHexIntLongToFloat("0x0A0A00", false); // Returns 2570.0f
parseHexToDouble
将十六进制字符串转换为Double。
语法:
int parseHexToDouble(String hex[, boolean bigEndian])
参数:
- hex:
string- 大端字节序的十六进制字符串。 - bigEndian:
boolean- 可选,为true时使用大端(BE)字节序,否则为小端(LE)。
返回值:
解析后的双精度值。
示例:
1
2
3
4
return parseHexToDouble("409B04B10CB295EA"); // Returns 1729.1729
return parseHexToDouble("409B04B10CB295EA", false); // Returns -2.7208640774822924E205
return parseHexToDouble("409B04B10CB295EA", true); // Returns 1729.1729
return parseHexToDouble("EA95B20CB1049B40", false); // Returns 1729.1729
parseLittleEndianHexToDouble
[parseHexToDouble(hex, false)]的别名(#parsehextodouble)
语法:
double parseLittleEndianHexToDouble(String hex)
parseBigEndianHexToDouble
[parseBigEndianHexToDouble(hex, true)]的别名(#parsehextodouble)
语法:
double parseBigEndianHexToDouble(String hex)
hexToBytes列表或数组
hexToBytes
将十六进制字符串转换为整数值列表,其中每个整数代表一个字节。
语法:
*List
参数:
- hex:
string- 大端字节序的十六进制字符串。
返回值:
解析后的整数值列表。
示例:
1
return hexToBytes("0x01752B0367FA000500010488FFFFFFFFFFFFFFFF33"); // Returns [1, 117, 43, 3, 103, -6, 0, 5, 0, 1, 4, -120, -1, -1, -1, -1, -1, -1, -1, -1, 51]
hexToBytesArray
将十六进制字符串转换为单字节值数组。
语法:
byte[] hexToBytesArray(String hex)
参数:
- hex:
string- 大端字节序的十六进制字符串。
返回值:
解析后的单字节值数组。
示例:
1
2
return hexToBytesArray("AABBCCDDEE"); // Returns [(byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE]
// Returns [-86, -69, -52, -35, -18]
parseBytes
bytesToHex
将整数值列表(其中每个整数代表一个字节)转换为十六进制字符串。
语法:
*String bytesToHex(List
参数:
- bytes:
byte[]或List of integer- 字节数组或整数值列表,其中每个整数代表一个字节。
返回值:
返回十六进制字符串。
示例:
1
2
3
4
var bytes = [0xBB, 0xAA];
return bytesToHex(bytes); // Returns "BBAA"
var list = [-69, 83];
return bytesToHex(list); // Returns "BB53"
parseBytesToInt
将具有给定偏移量的字节数组转换为int值,带有长度和可选字节序。
语法:
*int parseBytesToInt([byte[] or List
参数:
- data:
byte[]或List of Byte- 字节数组。 - offset:
int- 可选,数组中的偏移量。 - length:
int- 可选,以字节为单位的长度,小于或等于4。 - bigEndian:
boolean- 可选,false为小端序,否则为大端序。
返回值:
整数值。
示例:
1
2
3
4
var bytes = [0xAA, 0xBB, 0xCC, 0xDD];
return parseBytesToInt(bytes, 0, 3); // Returns 11189196 in Decimal or 0xAABBCC
return parseBytesToInt(bytes, 0, 3, true); // Returns 11189196 in Decimal or 0xAABBCC
return parseBytesToInt(bytes, 0, 3, false); // Returns 13417386 in Decimal or 0xCCBBAA
parseBytesToLong
将具有给定偏移量的字节数组转换为long值,带有长度和可选字节序。
语法:
*int parseBytesToInt([byte[] or List
参数:
- data:
byte[]或List of Byte- 字节数组。 - offset:
int- 可选,数组中的偏移量。 - length:
int- 可选,以字节为单位的长度,小于或等于4。 - bigEndian:
boolean- 可选,false为小端序,否则为大端序。
返回值:
长整数值。
示例:
1
2
3
4
var longValByte = [64, -101, 4, -79, 12, -78, -107, -22];
return parseBytesToLong(longValByte, 0, 8); // Returns 4655319798286292458L == 0x409B04B10CB295EAL
return parseBytesToLong(longValByte, 0, 8, false); // Returns -1543131529725306048L == 0xEA95B20CB1049B40L
parseBytesToFloat
将具有给定偏移量的字节数组转换为浮点数,带有长度和可选字节序。
语法:
*int parseBytesToFloat([byte[] or List
参数:
- data:
byte[]或List of Byte- 字节数组。 - offset:
int- 可选,数组中的偏移量。 - length:
int- 可选,以字节为单位的长度,小于或等于4。 - bigEndian:
boolean- 可选,false为小端序,否则为大端序。
返回值:
浮点值。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
var bytes = [0x0A];
return parseBytesToFloat(bytes); // Returns 1.4E-44f
var floatValByte = [0x41, 0xEA, 0x62, 0xCC];
return parseBytesToFloat(floatValByte, 0); // Returns 29.29824f
return parseBytesToFloat(floatValByte, 0, 2, false); // Returns 8.4034E-41f
return parseBytesToFloat(floatValByte, 0, 2, true); // Returns 2.3646E-41f
return parseBytesToFloat(floatValByte, 0, 3, false); // Returns 9.083913E-39f
return parseBytesToFloat(floatValByte, 0, 3, true); // Returns 6.053388E-39f
return parseBytesToFloat(floatValByte, 0, 4, false); // Returns -5.948442E7f
var floatValList = [65, -22, 98, -52];
return parseBytesToFloat(floatValList, 0); // Returns 29.29824f
return parseBytesToFloat(floatValList, 0, 4, false); // Returns -5.948442E7f
parseBytesIntToFloat
将具有给定偏移量的字节数组转换为浮点数,带有长度和可选字节序。
语法:
*int parseBytesToFloat([byte[] or List
参数:
- data:
byte[]或List of Byte- 字节数组。 - offset:
int- 可选,数组中的偏移量。 - length:
int- 可选,以字节为单位的长度,小于或等于4。 - bigEndian:
boolean- 可选,false为小端序,否则为大端序。
返回值:
浮点值。
示例:
1
2
3
4
5
6
7
var intValByte = [0x00, 0x00, 0x00, 0x0A];
return parseBytesIntToFloat(intValByte, 3, 1, true); // Returns 10.0f
return parseBytesIntToFloat(intValByte, 3, 1, false); // Returns 10.0f
return parseBytesIntToFloat(intValByte, 2, 2, true); // Returns 10.0f
return parseBytesIntToFloat(intValByte, 2, 2, false); // Returns 2560.0f
return parseBytesIntToFloat(intValByte, 0, 4, true); // Returns 10.0f
return parseBytesIntToFloat(intValByte, 0, 4, false); // Returns 1.6777216E8f
示例(经纬度):
1
2
3
4
5
6
var dataAT101 = "0x01756403671B01048836BF7701F000090722050000";
var byteAT101 = hexToBytes(dataAT101);
var offset = 9;
return parseBytesIntToFloat(byteAT101, offset, 4, false) / 1000000; // Returns 24.62495f
return parseBytesIntToFloat(byteAT101, offset + 4, 4, false) / 1000000; // Returns 118.030576f
parseBytesLongToDouble
将具有给定偏移量的字节数组转换为double值,带有长度和可选字节序。
语法:
*int parseBytesToDouble([byte[] or List
参数:
- data:
byte[]或List of Byte- 字节数组。 - offset:
int- 可选,数组中的偏移量。 - length:
int- 可选,以字节为单位的长度,小于或等于4。 - bigEndian:
boolean- 可选,false为小端序,否则为大端序。
返回值:
双精度值。
示例(经纬度):
1
2
3
4
5
6
7
var coordinatesAsHex = "0x32D009423F23B300B0106E08D96B6C00";
var coordinatesasBytes = hexToBytes(coordinatesAsHex);
var offset = 0;
var factor = 1e15;
return parseBytesLongToDouble(coordinatesasBytes, offset, 8, false) / factor; // Returns 50.422775429058610d, latitude
return parseBytesLongToDouble(coordinatesasBytes, offset + 8, 8, false) / factor; // Returns 30.517877378257072d, longitude
bytesToExecutionArrayList
将字节数组转换为字节数组的ArrayList实现,带有给定的偏移量、长度和可选字节序。
语法:
*ExecutionArrayList
参数:
- bytes:
byte[]- 字节数组。
返回值:
ExecutionArrayList
示例:
1
2
var bytes = [0xAA, 0xBB, 0xCC, 0xDD];
return bytesToExecutionArrayList(bytes); // Returns ExecutionArrayList<Byte> value with size = 4, includes: [-86, -69, -52, -35]
parseBinaryArray
parseByteToBinaryArray
将字节转换为二进制数组。
根据给定的可选binLength和字节序,将一个字节解析为二进制数组。
语法:
byte[] parseByteToBinaryArray(byte byteValue[, int binLength, boolean bigEndian])
参数:
- byteValue:
byte- 字节值。 - binLength:
int- 可选,输出二进制数组的长度。 - bigEndian:
boolean- 可选,false为小端序,否则为大端序。
返回值:
byte[]值。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var byteVal = 0x39;
return parseByteToBinaryArray(byteVal); // Returns byte[8] value => [0, 0, 1, 1, 1, 0, 0, 1]
return parseByteToBinaryArray(byteVal, 3); // Returns byte[3] value => [0, 0, 1]
return parseByteToBinaryArray(byteVal, 8, false); // Returns byte[8] value => [1, 0, 0, 1, 1, 1, 0, 0]
return parseByteToBinaryArray(byteVal, 5, false); // Returns byte[5] value => [1, 0, 0, 1, 1]
return parseByteToBinaryArray(byteVal, 4, false); // Returns byte[4] value => [1, 0, 0, 1]
return parseByteToBinaryArray(byteVal, 3, false); // Returns byte[3] value => [1, 0, 0]
var value = parseByteToBinaryArray(byteVal, 6, false); // Returns byte[6] value => [1, 0, 0, 1, 1, 1]
var actualLowCurrent1Alarm = value[0];
var actualHighCurrent1Alarm = value[1];
var actualLowCurrent2Alarm = value[2];
var actualHighCurrent2Alarm = value[3];
var actualLowCurrent3Alarm = value[4];
var actualHighCurrent3Alarm = value[5];
parseBytesToBinaryArray
将字节数组/列表转换为给定长度的二进制数组。
语法:
*byte[] parseBytesToBinaryArray([byte[] or List
参数:
- byteValue:
byte[]或List of Byte- 字节数组。 - binLength:
int- 可选,输出二进制数组的长度。
返回值:
byte[]值。
示例:
1
2
3
4
5
var bytesVal = [0xCE, 0xB2];
return parseBytesToBinaryArray(bytesVal); // Returns byte[16] value => [1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0]
return parseBytesToBinaryArray(bytesVal, 15); // Returns byte[15] value => [1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0]
return parseBytesToBinaryArray(bytesVal, 14); // Returns byte[14] value => [0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0]
return parseBytesToBinaryArray(bytesVal, 2); // Returns byte[2] value => [1, 0]
parseLongToBinaryArray
将long值转换为给定长度的二进制数组。
语法:
byte[] parseLongToBinaryArray(long longValue[, int binLength])
参数:
- longValue:
long- long值。 - binLength:
int- 可选,输出二进制数组的长度。
返回值:
byte[]值。
示例:
1
2
3
var longValue = 52914L;
return parseLongToBinaryArray(longValue); // Returns byte[64] value => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0]
return parseLongToBinaryArray(longValue, 16); // Returns byte[16] value => [1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0]
parseBinaryArrayToInt
将二进制数组转换为int值,可选指定整数偏移量、长度和字节序。
语法:
*int parseBinaryArrayToInt([byte[] or List
参数:
- data:
byte[]或List of Byte- 字节数组。 - offset:
int- 可选,数组中的偏移量。 - length:
int- 可选,以字节为单位的长度。
返回值:
int值。
示例:
1
2
var binaryArrayToInt = parseBinaryArrayToInt([1, 0, 0, 1, 1, 1, 1, 1]); // Returns -97
var actualVolt = parseBinaryArrayToInt([1, 0, 0, 1, 1, 1, 1, 1], 1, 7); // Returns 31
parseNumber
parseInt
将输入字符串转换为整数。
语法:
Integer parseInt(String str[, String radix])
参数:
- str:
string- 包含要解析的整数表示的字符串。 - radix:
String- 可选,解析字符串时使用的进制。
返回值:
An 整数值。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
return parseInt("0"); // Returns 0
return parseInt("473"); // Returns 473
return parseInt("+42"); // Returns 42
return parseInt("-0", 10); // Returns 0
return parseInt("-0xFF"); // Returns -255
return parseInt("-FF", 16); // Returns -255
return parseInt("1100110", 2); // Returns 102
return parseInt("2147483647", 10); // Returns 2147483647
return parseInt("-2147483648", 10); // Returns -2147483648
return parseInt("Kona", 27); // Returns 411787
return parseInt("2147483648", 10); // throws a NumberFormatException
return parseInt("99", 8); // throws a NumberFormatException
return parseInt("Kona", 10); // throws a NumberFormatException
parseLong
将输入字符串转换为长整数。
语法:
Long parseLong(String str[, String radix])
参数:
- str:
string- 包含要解析的long表示的字符串。 - radix:
String- 可选,解析字符串时使用的进制。
返回值:
A 长整数值。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
return parseLong("0"); // Returns 0L
return parseLong("473"); // Returns 473L
return parseLong("+42"); // Returns 42L
return parseLong("-0", 10); // Returns 0L
return parseLong("-0xFFFF"); // Returns -65535L
return parseLong("-FFFF", 16); // Returns -65535L
return parseLong("11001101100110", 2); // Returns 13158L
return parseLong("777777777777777777777", 8); // Returns 9223372036854775807L
return parseLong("KonaLong", 27); // Returns 218840926543L
return parseLong("9223372036854775807", 10); // Returns 9223372036854775807L
return parseLong("-9223372036854775808", 10); // Returns -9223372036854775808L
return parseLong("9223372036854775808", 10); // throws a NumberFormatException
return parseLong("0xFGFFFFFF", 16); // throws a NumberFormatException
return parseLong("FFFFFFFF", 16); // throws a NumberFormatException
return parseLong("1787", 8); // throws a NumberFormatException
return parseLong("KonaLong", 10); // throws a NumberFormatException
return parseLong("KonaLong", 16); // throws a NumberFormatException
parseFloat
将输入字符串转换为浮点数。
语法:
Integer parseFloat(String str)
参数:
- str:
string- 要解析的字符串。
返回值:
A 浮点值。
示例:
1
return parseFloat("4.2"); // Returns 4.2f
parseDouble
将输入字符串转换为双精度浮点数。
语法:
Integer parseDouble(String str)
参数:
- str:
string- 要解析的字符串。
返回值:
双精度浮点值。
示例:
1
return parseDouble("4.2"); // Returns 4.2d
位控操作
ThingsBoard中的位操作允许操作整数、长整数和布尔值中的各个位。这些操作支持混合类型操作数(Integer、Long、Boolean),无需隐式类型转换,结果类型取决于操作的结果:Integer或Long。
支持的运算符:
1
2
3
4
5
6
- AND `&`:逐位比较,当两个位都为`1`时结果位为`1`。
- OR `|`:当对应位中至少一个为`1`时,将该位设为`1`。
- XOR `^`:当对应位不同时,将该位设为`1`。
- 左移 `<<`:将位向左移动,相当于将数字乘以`2^n`。
- 右移 `>>`:将位向右移动,相当于将数字除以`2^n`(保留符号位)。
- 无符号右移 `>>>`:将位向右移动,用零填充,不考虑符号位。
支持的数据类型组合
- Integer - Integer:产生Integer结果。
- Long - Long:产生Long结果。
- Boolean - Boolean:产生Integer结果。
- 混合类型(如Integer - Long、Long - Boolean、Boolean - Integer):操作确保输入类型之间的兼容性,结果类型根据精度或层级确定:
- 如果其中一个类型是Long,结果为Long。
- 如果一个类型是Boolean,另一个是Integer,结果为Integer。
- 如果两个类型都是Boolean,结果也为Integer。
示例:
Boolean - Boolean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var x = true;
var y = false;
var andResult = x & y;
return andResult; // Returns 0
var orResult = x | y;
return orResult; // Returns 1
var xorResult = x ^ y;
return xorResult; // Returns 1
var leftShift = x << y;
return leftShift; // Returns 1
var rightShift = x >> y;
return rightShift; // Returns 1
var rightUnShift = x >>> y;
return rightUnShift; // Returns 1
Mixed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var x = true;
var y = false;
var i = 10;
var b = -14;
var l = 9223372036854775807;
var andResult = x & b;
return andResult; // Returns 0
var orResult = i | y;
return orResult; // Returns 10
var xorResult = i ^ l;
return xorResult; // Returns 9223372036854775797L
var leftShift = l << i;
return leftShift; // Returns -1024L
var rightShift = l >> b;
return rightShift; // Returns 8191L
var rightUnShift = i >>> x;
return rightUnShift; // Returns 5
base64
base64ToHex
将Base64字符串解码为十六进制字符串。
语法:
String base64ToHex(String input)
参数:
- input:
String- Base64字符串。
返回值:
十六进制字符串
示例:
1
return base64ToHex("Kkk="); // Returns "2A49"
bytesToBase64
将字节数组编码为Base64字符串。
语法:
String bytesToBase64(byte[] bytes)
参数:
- bytes:
List of integer- 整数值列表,其中每个整数代表一个字节。
返回值:
Base64字符串。
示例:
1
return bytesToBase64([42, 73]); // Returns "Kkk="
base64转字节数组或列表
base64ToBytes
将Base64字符串解码为字节数组。
语法:
byte[] base64ToBytes(String input)
参数:
- input:
String- Base64字符串。
返回值:
字节数组。
示例:
1
return base64ToBytes("Kkk="); // Returns [42, 73]
base64ToBytesList
将Base64字符串解码为字节列表。
语法:
*List
参数:
- input:
String- Base64字符串。
返回值:
字节数组。
示例:
1
return base64ToBytesList("AQIDBAU="); // Returns ExecutionArrayList<Byte> value with size = 5, includes: [1, 2, 3, 4, 5]
toFlatMap
递归遍历给定对象并创建单层JSON对象。
如果传入消息包含数组,转换后的值的键将包含元素的索引。
语法:
1
2
3
4
Map<String, Object> toFlatMap(Map<String, Object> json)
Map<String, Object> toFlatMap(Map<String, Object> json, boolean pathInKey)
Map<String, Object> toFlatMap(Map<String, Object> json, List<String> excludeList)
Map<String, Object> toFlatMap(Map<String, Object> json, List<String> excludeList, boolean pathInKey)
参数:
- json
Map<String, Object>- 输入JSON对象。 - excludeList
List<String>- 可选要从结果中排除的键列表。默认值:[]。 - pathInKey
boolean- 可选是否在键中添加路径。默认值:true。
返回值:
JSON对象
示例:
Input:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"key1": "value1",
"key2": 12,
"key3": {
"key4": "value4",
"key5": 34,
"key6": [{
"key7": "value7"
},
{
"key8": "value8"
},
"just_string_value_in_array",
56
],
"key9": {
"key10": ["value10_1", "value10_2", "value10_3"]
}
},
"key_to_overwrite": "root_value",
"key11": {
"key_to_overwrite": "second_level_value"
}
}
toFlatMap(json)
预期的行为——获取单级对象,其中包含嵌套路径。
1
return toFlatMap(json);
Output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"key1": "value1",
"key2": 12,
"key3.key4": "value4",
"key3.key5": 34,
"key3.key6.0.key7": "value7",
"key3.key6.1.key8": "value8",
"key3.key6.2": "just_string_value_in_array",
"key3.key6.3": 56,
"key3.key9.key10.0": "value10_1",
"key3.key9.key10.1": "value10_2",
"key3.key9.key10.2": "value10_3",
"key_to_overwrite": "root_value",
"key11.key_to_overwrite": "second_level_value"
}
toFlatMap(json, pathInKey)
预期的行为——获取不包含嵌套路径的单级对象。
key_to_overwrite应包含来自key11.key_to_overwrite的值。
1
return toFlatMap(json, false);
Output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"key1": "value1",
"key2": 12,
"key4": "value4",
"key5": 34,
"key7": "value7",
"key8": "value8",
"key6.2": "just_string_value_in_array",
"key6.3": 56,
"key10.0": "value10_1",
"key10.1": "value10_2",
"key10.2": "value10_3",
"key_to_overwrite": "second_level_value"
}
如你所见,key_to_overwrite的值是second_level_value而非root_value。
toFlatMap(json, excludeList)
预期的行为——获取键中包含路径的单级对象,不包含key1和key3键。
1
return toFlatMap(json, ["key1", "key3"]);
Output:
1
2
3
4
5
{
"key2": 12,
"key_to_overwrite": "root_value",
"key11.key_to_overwrite": "second_level_value"
}
如你所见,key1和key3已从输出中移除。排除功能可在任何层级对传入的键生效。
toFlatMap(json, excludeList, pathInKey)
预期的行为——获取键中不包含路径的单级对象,不包含key2和key4键。
key_to_overwrite应包含来自key11.key_to_overwrite的值。
1
return toFlatMap(json, ["key2", "key4"], false);
Output:
1
2
3
4
5
6
7
8
9
10
11
12
{
"key1": "value1",
"key5": 34,
"key7": "value7",
"key8": "value8",
"key6.2": "just_string_value_in_array",
"key6.3": 56,
"key10.0": "value10_1",
"key10.1": "value10_2",
"key10.2": "value10_3",
"key_to_overwrite": "second_level_value"
}
如你所见,key2和key4已从输出中排除,key_to_overwrite的值是second_level_value。
tbDate:
Tbel库使用JavaScript Date中的所有标准JavaScript方法,如“toLocaleString”、“toISOString”及其他方法。
输入数据格式:
- 字符串,可选:pattern、locale、time zone
- 整数(年、月等),可选:pattern、locale、time zone
Locale默认值:UTC;
Time zone Id默认值:ZoneId.systemDefault();
返回值:
以字符串形式表示的Date对象,使用locale默认值:”UTC”,time zone Id默认值:ZoneId.systemDefault()。
字符串,可选:pattern、locale、time zone
示例:
- 输入数据格式:仅一个字符串参数(输入参数中的时区可变),不含pattern:
1
2
3
4
5
假设输入: "2007-12-03T10:15:30.00Z" TZ = UTC
"2007-12-03T10:15:30.00" TZ = ZoneId.systemDefault() instant
"2007-12-03T10:15:30.00-04" TZ = "-04"
"2007-12-03T10:15:30.00+02:00" TZ = "+02"
"2007-12-03T10:15:30.00+03:00:00" TZ = "+03"
1
2
var d = new Date("2023-08-06T04:04:05.123Z"); // TZ => "UTC"
var dIso = d.toISOString(); // return "2023-08-06T04:04:05.123Z" ZoneId "UTC"
1
2
var d = new Date("2023-08-06T12:04:05.123"); // TZ => Default
var dIso = d.toISOString(); // return "2023-08-06T16:04:05.123Z" (if ZoneId.systemDefault(): "America/New_York" = "-04:00")
1
2
var d = new Date("2023-08-06T04:04:05.00-04"); // TZ => "-04"
var dIso = d.toISOString(); // return "2023-08-06T08:04:05Z" ZoneId "America/New_York" = "-04:00"
1
2
var d = new Date("2023-08-06T04:04:05.00+02:00"); // TZ => "+02:00"
var dIso = d.toISOString(); // return "2023-08-06T02:04:05Z" ZoneId "Europe/Berlin" = "+02:00"
1
2
var d = new Date("2023-08-06T04:04:05.00+03:00:00"); // TZ => "+03:00:00"
var dIso = d.toISOString(); // return "2023-08-06T01:04:05Z" ZoneId "Europe/Kyiv" = "+03:00"
1
2
3
4
5
假设RFC-1123值: "Tue, 3 Jun 2008 11:05:30 GMT" TZ = UTC
"Tue, 3 Jun 2008 11:05:30" TZ = ZoneId.systemDefault() instant
"Tue, 3 Jun 2008 11:05:30 -03" TZ = "-03"
"Tue, 3 Jun 2008 11:05:30 -0200" TZ = "-02"
"Tue, 3 Jun 2008 11:05:30 +043056" TZ = "+04:30:56"
1
2
var d = new Date("Tue, 3 Jun 2008 11:05:30 GMT"); // TZ => "GMT"
var dIso = d.toISOString(); // return "2008-06-03T11:05:30Z" ZoneId "GMT" = "0"
1
2
var d = new Date("Tue, 3 Jun 2008 11:05:30 +043056"); // TZ => "+043056"
var dIso = d.toISOString(); // return "2008-06-03T06:34:34Z" ZoneId "????" = "+04:30:56"
- 输入数据格式:字符串 + Pattern:
1
2
3
var pattern = "yyyy-MM-dd HH:mm:ss.SSSXXX";
var d = new Date("2023-08-06 04:04:05.000Z", pattern); // Pattern without TZ => ZoneId "UTC"
var dIso = d.toISOString(); // return "2023-08-06T04:04:05Z" ZoneId "UTC" = "00:00"
1
2
3
var pattern = "yyyy-MM-dd HH:mm:ss.SSSXXX";
var d = new Date("2023-08-06 04:04:05.000-04:00", pattern); // Pattern with TZ => "-04:00"
var dIso = d.toISOString(); // return "2023-08-06T08:04:05Z" ZoneId "America/New_York" = "-04:00"
1
2
3
var pattern = "yyyy-MM-dd HH:mm:ss.SSS";
var d = new Date("2023-08-06 12:04:05.000", pattern); // Pattern without TZ, TZ = ZoneId.systemDefault() instant
var dIso = d.toISOString(); // return "2023-08-06T16:04:05Z" (if ZoneId.systemDefault(): "America/New_York" = "-04:00")
- 输入数据格式:字符串 + Pattern + Locale:
1
2
3
4
var pattern = "hh:mm:ss a, EEE M/d/uuuu";
var d = new Date("12:15:30 PM, So. 10/09/2022", pattern, "de"); // Pattern without TZ, TZ = ZoneId.systemDefault() instant
var dIso = d.toISOString(); // return "2022-10-09T16:15:30Z" (if ZoneId.systemDefault(): "America/New_York" = "-04:00")
var dLocal= d.toLocaleString("de"); // return "09.10.22, 12:15:30"
1
2
3
4
var pattern = "hh:mm:ss a, EEE M/d/uuuu";
var d = new Date("12:15:30 PM, Sun 10/09/2022", pattern, "en-US"); // Pattern without TZ, TZ = ZoneId.systemDefault() instant
var dIso = d.toISOString(); // return "2022-10-09T16:15:30Z" (if ZoneId.systemDefault(): "America/New_York" = "-04:00")
var dLocal = d.toLocaleString("en-US"); // return "10/9/22, 12:15:30 PM"
1
2
3
4
var pattern = "hh:mm:ss a, EEE M/d/uuuu";
var d = new Date("02:15:30 PM, Sun 10/09/2022", pattern, "de"); // return: Error: could not create constructor
// The pattern with input parameter of date does not match the locale
// Locale = "de", input parameter "day of the week" is "Sun", should be "So.".
- 输入数据格式:字符串 + Pattern + Locale + Time Zone:
1
2
3
4
5
var pattern = "yyyy-MM-dd HH:mm:ss.SSSXXX";
var d = new Date("2023-08-06 04:04:05.000+02:00", pattern, "de", "America/New_York"); // Pattern with TZ => "+02:00" but `Time Zone` as parameter = "America/New_York" = "-04:00"
var dIso = d.toISOString(); // return "2023-08-06T08:04:05Z" ZoneId "America/New_York" = "-04:00"
var dLocal_de = d.toLocaleString("de"); // return "06.08.23, 04:04:05" (if ZoneId.systemDefault(): "America/New_York" = "-04:00")
var dLocal_us = d.toLocaleString("en-US"); // return "8/6/23, 4:04:05 AM"
Instant(年、月等),可选:time zone
1
2
3
4
var d = new Date(2023, 8, 6, 4, 4, 5, "America/New_York");
var dLocal = d.toLocaleString(); // return "2023-08-06 04:04:05" (Locale: "UTC", ZoneId "America/New_York")
var dIso = d.toISOString(); // return "2023-08-06T08:04:05Z" (if ZoneId.systemDefault(): "America/New_York" = "-04:00")
var dDate = d; // return "Sunday, August 6, 2023 at 4:04:05 AM Eastern Daylight Time"
1
2
3
4
5
var d = new Date(2023, 8, 6, 4, 4, 5, "Europe/Berlin");
var dLocal = d.toLocaleString(); // return "2023-08-05 22:04:05" (Locale: "UTC", (if ZoneId.systemDefault(): "America/New_York" = "-04:00"))
var dLocal_us = d.toLocaleString("en-us", "America/New_York"); // return "8/5/23, 10:04:05 PM" (Locale: "en-us", ZoneId "America/New_York")
var dIso = d.toISOString(); // return "2023-08-06T02:04:05Z"
var dDate = d; // return "Saturday, August 5, 2023 at 22:04:05 AM Eastern Daylight Time" (if ZoneId.systemDefault(): "America/New_York" = "-04:00")
区域设置
语法:
String toLocaleString(String locale)
参数:
Time zone Id默认值:ZoneId.systemDefault();
- locale:
string- 要使用的语言特定格式。
返回值:
以字符串形式表示的Date对象,使用locale设置,time zone Id默认值:ZoneId.systemDefault()。
示例: 不含TZ的输入日期(TZ默认值 = ZoneId.systemDefault())
1
2
3
4
var d = new Date(2023, 8, 6, 4, 4, 5); // Parameters (int year, int month, int dayOfMonth, int hours, int minutes, int seconds) => TZ Default = ZoneId.systemDefault();
var dLocal = d.toLocaleString("en-US"); // return "8/6/23, 4:04:05 AM" (Locale: "en-US")
var dIso = d.toISOString(); // return Default = ZoneId.systemDefault: "2023-08-06T08:04:05Z", (if ZoneId.systemDefault(): "America/New_York" = "-04:00");
var dDate = d; // return "Sunday, August 6, 2023 at 4:04:05 AM Eastern Daylight Time" (if ZoneId.systemDefault(): "America/New_York" = "-04:00");
1
2
3
4
var d = new Date("2023-08-06T04:04:05.000"); // Parameter (String 'yyyy-MM-ddThh:mm:ss.ms') => TZ Default = ZoneId.systemDefault():
var dIso = d.toISOString(); // return "2023-08-06T08:04:05Z" (if ZoneId.systemDefault(): "America/New_York" = "-04:00");
var dLocal_de = d.toLocaleString("de"); // return "06.08.23, 04:04:05" (Locale: "de", ZoneId.systemDefault());
var dLocal_utc = d.toLocaleString("UTC"); // return "2023-08-06 04:04:05" (Locale: "UTC", ZoneId.systemDefault());
含TZ的输入日期(TZ = 参数TZ或’Z’等于’UTC’)
1
2
3
4
5
var d = new Date(2023, 8, 6, 4, 4, 5, "Europe/Berlin"); // Parameters (int year, int month, int dayOfMonth, int hours, int minutes, int seconds, TZ) => TZ "Europe/Berlin";
var dIso = d.toISOString(); // return "2023-08-06T02:04:05Z";
var dLocal1 = d.toLocaleString("UTC"); // return "2023-08-05 22:04:05" (Locale: "UTC", (if ZoneId.systemDefault(): "America/New_York" = "-04:00"));
var dLocal2 = d.toLocaleString("en-us"); // return "8/5/23, 10:04:05 PM" (Locale: "en-US", (if ZoneId.systemDefault(): "America/New_York" = "-04:00"));
var dLocal3 = d.toLocaleString("de"); // return "05.08.23, 22:04:05" (Locale: "de", (if ZoneId.systemDefault(): "America/New_York" = "-04:00"));
区域设置、时区
语法:
String toLocaleString(String locale, String tz)
参数:
- locale:
string- 要使用的语言特定格式。 - tz:
string- 本地时区Id。
返回值:
以字符串形式表示的Date对象,使用locale设置和时区Id。
示例:
1
2
3
4
5
var d = new Date(2023, 8, 6, 4, 4, 5, "Europe/Berlin"); // Parameters (int year, int month, int dayOfMonth, int hours, int minutes, int seconds, TZ) => TZ "Europe/Berlin";
var dIso = d.toISOString(); // return "2023-08-06T02:04:05Z" (if ZoneId.systemDefault(): "America/New_York" = "-04:00");
var dLocal1 = d.toLocaleString("UTC"); // return "2023-08-05 22:04:05" (Locale: "UTC", (if ZoneId.systemDefault(): "America/New_York" = "-04:00"));
var dLocal2 = d.toLocaleString("en-us", "America/New_York"); // return "8/5/23, 10:04:05 PM" (Locale: "en-US", ZoneId "America/New_York" = "-04:00")
var dLocal3 = d.toLocaleString("de", "Europe/Berlin"); // return "06.08.23, 04:04:05" (Locale: "de", ZoneId "Europe/Berlin" = "+02:00")
区域设置、格式模式(使用Map选项)
语法:
String toLocaleString(String locale, String optionsStr)
参数:
- locale:
string- 要使用的语言特定格式。 - pattern:
string- Pattern,时区Id,要使用的日期/时间字符串格式。
返回值:
以字符串形式表示的Date对象,使用locale设置,{“timeZone”: “时区Id”, “dateStyle”: “full/long/medium/short”, “timeStyle”: “full/long/medium/short”, “pattern”: “M/d/yyyy, h:mm:ss a”}。
示例:
1
2
3
4
5
6
7
var d = new Date("2023-08-06T04:04:05.00Z"); // TZ => "UTC"
var dIso = d.toISOString(); // return "2023-08-06T04:04:05Z"
var dLocal1 = d.toLocaleString(); // return "2023-08-06 00:04:05" (Locale: Default "UTC", ZoneId: (if ZoneId.systemDefault(): "America/New_York" = "-04:00"));
var options = {"timeZone":"Europe/Berlin"}; // TZ = "+02:00"
var optionsStr = JSON.stringify(options);
var dLocal2 = d.toLocaleString("en-US", optionsStr); // "8/6/23, 6:04:05 AM" (Locale: "en-US", options: ZoneId => "Europe/Berlin" = "+02:00");
1
2
3
4
5
var d = new Date("2023-08-06T04:04:05.000"); // TZ => Default = ZoneId.systemDefault
var dIso = d.toISOString(); // return "2023-08-06T08:04:05Z" (if ZoneId.systemDefault(): "America/New_York" = "-04:00")
var options = {"timeZone":"Europe/Berlin"};
var optionsStr = JSON.stringify(options);
var dLocal1 = d.toLocaleString("en-US", optionsStr); // return "8/6/23, 10:04:05 AM" (Locale: "en-US", options: ZoneId => "Europe/Berlin" = "+02:00");
1
2
3
4
5
var d = new Date(2023, 8, 6, 4, 4, 5); // TZ => Default = ZoneId.systemDefault
var dIso = d.toISOString(); // return "2023-08-06T08:04:05Z" (if ZoneId.systemDefault(): "America/New_York" = "-04:00")
var options = {"timeZone":"Europe/Berlin", "pattern": "M-d/yyyy, h:mm=ss a"};
var optionsStr = JSON.stringify(options);
var dLocal1 = d.toLocaleString("en-US", optionsStr); // return "8-6/2023, 10:04=05 AM" (options: pattern, Locale = "en-US", ZoneId => "Europe/Berlin" = "+02:00");
1
2
3
4
5
6
7
var d = new Date(2023, 8, 6, 4, 4, 5, "UTC"); // TZ => "UTC"
var dIso = d.toISOString(); // return "2023-08-06T04:04:05Z"
var options = {"timeZone":"Europe/Berlin","dateStyle":"full","timeStyle":"full"};
var optionsStr = JSON.stringify(options);
var dLocal1 = d.toLocaleString("uk-UA", optionsStr); // return "неділя, 6 серпня 2023 р. о 06:04:05 за центральноєвропейським літнім часом"
var dLocal2 = d.toLocaleString("en-US", optionsStr); // return "Sunday, August 6, 2023 at 6:04:05 AM Central European Summer Time"
var dLocal3 = d.toLocaleString("de", optionsStr); // return "Sonntag, 6. August 2023 um 06:04:05 Mitteleuropäische Sommerzeit"
单独添加时间单位的函数:年、月、周、日、时、分、秒和毫秒。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
var stringDateUTC = "2024-01-01T10:00:00.00Z";
var d = new Date(stringDateUTC); // TZ => "UTC"
var dIso = d.toISOString(); // return 2024-01-01T10:00:00Z
d.addYears(1);
d.toISOString(); // return 2025-01-01T10:00:00Z
d.addYears(-2);
d.toISOString(); // return 2023-01-01T10:00:00Z
d.addMonths(2);
d.toISOString(); // return 2023-03-01T10:00:00Z
d.addMonths(10);
d.toISOString(); // return 2024-01-01T10:00:00Z
d.addMonths(-13);
d.toISOString(); // return 2022-12-01T10:00:00Z
d.addWeeks(4);
d.toISOString(); // return 2022-12-29T10:00:00Z
d.addWeeks(-5);
d.toISOString(); // return 2022-11-24T10:00:00Z
d.addDays(6);
d.toISOString(); // return 2022-11-30T10:00:00Z
d.addDays(45);
d.toISOString(); // return 2023-01-14T10:00:00Z
d.addDays(-50);
d.toISOString(); // return 2022-11-25T10:00:00Z
d.addHours(23);
d.toISOString(); // return 2022-11-26T09:00:00Z
d.addHours(-47);
d.toISOString(); // return 2022-11-24T10:00:00Z
d.addMinutes(59);
d.toISOString(); // return 2022-11-24T10:59:00Z
d.addMinutes(-60);
d.toISOString(); // return 2022-11-24T09:59:00Z
d.addSeconds(59);
d.toISOString(); // return 2022-11-24T09:59:59Z
d.addSeconds(-60);
d.toISOString(); // return 2022-11-24T09:58:59Z
d.addNanos(999999);
d.toISOString(); // return 2022-11-24T09:58:59.000999999Z
d.addNanos(-1000000);
d.toISOString(); // return 2022-11-24T09:58:58.999999999Z
地理围栏实用函数
isInsidePolygon
检查给定的地理坐标是否在给定多边形的范围内。
语法:
boolean isInsidePolygon(double latitude, double longitude, String perimeter)
参数:
- latitude:
double– 坐标的纬度。 - longitude:
double– 坐标的经度。 - perimeter:
String– 使用嵌套数组格式表示多边形的字符串:- 第一个数组定义多边形的外边界。
- 任何附加数组定义内边界(孔洞)。
- 每个点定义为
[纬度, 经度]对。
返回值:
表示结果的布尔值:
- 如果坐标在多边形内则返回
true。 - 否则返回
false。
示例:
1
2
3
4
5
6
7
var perimeter = "[[[37.7810,-122.4210],[37.7890,-122.3900],[37.7700,-122.3800],[37.7600,-122.4000],[37.7700,-122.4250],[37.7810,-122.4210]],[[37.7730,-122.4050],[37.7700,-122.3950],[37.7670,-122.3980],[37.7690,-122.4100],[37.7730,-122.4050]]]";
// Outside the polygon
return isInsidePolygon(37.8000, -122.4300, perimeter); // Returns false
// Inside the polygon
return isInsidePolygon(37.7725, -122.4010, perimeter); // Returns true
// Inside the hole
return isInsidePolygon(37.7700, -122.4030, perimeter); // Returns false
isInsideCircle
检查给定的地理坐标是否在圆形范围内。
语法:
boolean isInsideCircle(double latitude, double longitude, String perimeter)
参数:
- latitude:
double– 坐标的纬度。 - longitude:
double– 坐标的经度。 - perimeter:
String– 表示圆形的JSON字符串,包含以下字段:latitude:圆心的纬度。longitude:圆心的经度。radius:圆的半径。radiusUnit:可选,定义半径的单位。默认为METER。支持的值:METER、KILOMETER、FOOT、MILE、NAUTICAL_MILE。
返回值:
表示结果的布尔值:
- 如果坐标在圆内则返回
true。 - 否则返回
false。
示例:
1
2
3
4
5
var perimeter = "{\"latitude\":37.7749,\"longitude\":-122.4194,\"radius\":3000,\"radiusUnit\":\"METER\"}";
// Outside the circle
return isInsideCircle(37.8044, -122.2712, perimeter); // Returns false
// Inside the circle
return isInsideCircle(37.7599, -122.4148, perimeter); // Returns true