产品定价 立即试用
云平台
北美地区
文档 > 其他功能 > ThingsBoard表达语言(TBEL)
入门
指南 API 常见问题
目录

ThingsBoard表达式语言 (TBEL)

ThingsBoard在Rule EngineData 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有两种写法:

  1. 显式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;
}

  1. 不使用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
文档信息图标

注意
sort/toSorted操作:

  • 如果列表仅包含数值(12234或数值形式的字符串”12234”)- sort/toSorted…操作将按数值类型排序;
  • 如果列表包含一个或多个非数值(”123K45”或”FEB”或{345: “re56”})- sort/toSorted…操作将按字符串类型排序;

列表 - 不可修改

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* 字面量可使用后缀 BI(必须大写)。

1
2
104.39484B // BigDecimal
8.4I // BigInteger

布尔字面量由保留关键字 truefalse 表示。

null字面量由保留关键字 nullnil 表示。

使用Java类

TBEL实现允许使用 java.utiljava.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库中,maplist类对其主要方法进行了扩展支持,类似于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 whiledo until在TBEL中已实现,遵循与Java相同的约定,其中untilwhile的反义。

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 stringToBytes(String input[, String charsetName])*

参数:

  • 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[, String charsetName])*

参数:

  • 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)*

参数:

  • 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()函数:

  • encodeURI()函数将字符转义为UTF-8编码单元,每个八位字节以%XX格式编码,必要时在左侧补0。UTF-16中的孤立代理项不代表有效的Unicode字符。
  • Tbel库包含大部分标准JavaScript方法,如encodeURI()
  • encodeURI()对除以下字符外的所有字符进行转义:
1
AZ az 09 - _ . ! ~ * ' ( ) ; / ? : @ & = + $ , #

语法:

String encodeURI(String uri)

参数:

  • uri: String - 要编码为URI的字符串。

返回值:

表示将提供的字符串编码为URI的新字符串。

示例:

1
2
var uriOriginal = "-_.!~*'();/?:@&=+$,#ht://example.ж д a/path with spaces/?param1=Київ 1&param2=Україна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&param2=%D0%A3%D0%BA%D1%80%D0%B0%D1%97%D0%BD%D0%B02"

decodeURI

文档信息图标

注意
decodeURI()函数:

  • decodeURI()函数解码先前使用encodeURI()或类似方法编码的统一资源标识符(URI)。
  • Tbel库包含大部分标准JavaScript方法,包括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&param2=%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&param2=Україна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>。

语法:

*List printUnsignedBytes(List byteArray)*

参数:

  • 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

文档信息图标

注意
例如“0x0A”对应10.0f

  • 在此方法中,我们将其作为整数处理。

将十六进制字符串转换为浮点数。

语法:

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 hexToBytes(String hex)*

参数:

  • 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)* *String bytesToHex(byte[] bytes)*~~~~

参数:

  • 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[, int offset, int length, boolean bigEndian])*

参数:

  • 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[,int offset, int length, boolean bigEndian])*

参数:

  • 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

文档信息图标

注意
例如“0x0A”对应1.4E-44f

  • 在此方法中,我们将其作为浮点数处理。

将具有给定偏移量的字节数组转换为浮点数,带有长度和可选字节序。

语法:

*int parseBytesToFloat([byte[] or List ] data[, int offset, int length, boolean bigEndian])*

参数:

  • 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

文档信息图标

注意
例如“0x0A”对应10.0f“0x0A00”对应2560.0f

  • 在此方法中,我们将其作为整数处理。
  • 将字节数组转换为浮点数,其值等于将十六进制字符串转换为整数时得到的值。

将具有给定偏移量的字节数组转换为浮点数,带有长度和可选字节序。

语法:

*int parseBytesToFloat([byte[] or List ] data[, int offset, int length, boolean bigEndian])*

参数:

  • 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

文档信息图标

注意
例如“0x0A”对应10.0d“0x0A00”对应2’560.0d“0x0A0A0A0A”对应168’430’090.0d

  • 在此方法中,我们将其作为long处理。
  • 将字节数组转换为浮点数,其值等于将十六进制字符串转换为Long数值时得到的值。
  • 使用double类型对于6-7位小数精度的经纬度坐标具有足够的精度(精确到英寸级别)。
  • 经纬度的第6位小数可达到亚英尺级精度。

将具有给定偏移量的字节数组转换为double值,带有长度和可选字节序。

语法:

*int parseBytesToDouble([byte[] or List ] data[, int offset, int length, boolean bigEndian])*

参数:

  • 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 bytesToExecutionArrayList([byte[] bytes)*

参数:

  • 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[, int binLength])*

参数:

  • 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[, int offset, int length])*

参数:

  • 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`(保留符号位)。
- 无符号右移 `>>>`:将位向右移动,用零填充,不考虑符号位。

支持的数据类型组合

  1. Integer - Integer:产生Integer结果。
  2. Long - Long:产生Long结果。
  3. Boolean - Boolean:产生Integer结果。
  4. 混合类型(如Integer - Long、Long - Boolean、Boolean - Integer):操作确保输入类型之间的兼容性,结果类型根据精度或层级确定:
  • 如果其中一个类型是Long,结果为Long。
  • 如果一个类型是Boolean,另一个是Integer,结果为Integer。
  • 如果两个类型都是Boolean,结果也为Integer。
文档信息图标

注意
例如Boolean -(Integer / Long)或(Integer / Long)- Boolean

  • 布尔值被解释为1(true)或0(false),可以直接与整数或长整数交互。

示例:

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 base64ToBytesList(String input)*

参数:

  • 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
文档警告图标

如果参数pathInKey设置为false - 某些键可能会被新发现的值覆盖!
建议在包含不同层级相似键的对象中谨慎使用。

返回值:

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)

预期的行为——获取键中包含路径的单级对象,不包含key1key3键。

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"
}

如你所见,key1key3已从输出中移除。排除功能可在任何层级对传入的键生效。

toFlatMap(json, excludeList, pathInKey)

预期的行为——获取键中不包含路径的单级对象,不包含key2key4键。
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"
}

如你所见,key2key4已从输出中排除,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。支持的值:METERKILOMETERFOOTMILENAUTICAL_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