dd
我用的influxDB 1.8版本高版本我不清楚,因为1.x版本便于写sq语法。
influxDB时序库默认使用 UTC时区,并且无法通过配置来修改这个时区,很多文档说在查询数据的时候加上 tz('Asia/Shanghai')。
而这个在Windows环境下的influxdb会报错:
ERR: error parsing query: unable to find time zone Asia/Shanghai
首先我们来看下infulxdb数据库存储的time数据,我发现是以时间戳来存储的。
但是我们Java查询出来的时间是UTC时间格式
以上是问题描述,以下是解决思路。
pom文件
<!-- 时序库-->
<dependency>
<groupId>org.influxdb</groupId>
<artifactId>influxdb-java</artifactId>
<version>2.15</version>
</dependency>
我发现influxdb提供了时间工具类。解决思路先将2023-05-26T08:47:03.6147144Z 这种UTC格式转成 时间戳 再赋值给Date()对象转成CST时区时间;
UTC时间字符串转时间戳
long time = TimeUtil.fromInfluxDBTimeFormat("2023-05-30T02:09:05.3138263Z");
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//这样就得到了 2023-05-30 11:01:23
String timeStr = simpleDateFormat.format(new Date(time));
粘一段获取到influxdb数据后映射给Java对象的代码。
/**
* 查询,返回对象的list集合
*
* @param query
* @return
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public <T> List<T> fetchResults(String query, Class<?> clasz) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
List results = new ArrayList<>();
QueryResult queryResult = influxDB.query(new Query(query, Configurations.DATABASE_NAME));
queryResult.getResults().forEach(result -> {
result.getSeries().forEach(serial -> {
List<String> columns = serial.getColumns();
int fieldSize = columns.size();
serial.getValues().forEach(value -> {
Object obj = null;
try {
obj = clasz.newInstance();
for (int i = 0; i < fieldSize; i++) {
String fieldName = columns.get(i);
Field field = clasz.getDeclaredField(fieldName);
field.setAccessible(true);
Class<?> type = field.getType();
if (type == float.class) {
field.set(obj, Float.valueOf(value.get(i).toString()));
} else if (type == Long.class) {
field.set(obj, Long.valueOf(value.get(i).toString()));
} else if (type == Double.class) {
field.set(obj, Double.valueOf(value.get(i).toString()));
} else {
long time = TimeUtil.fromInfluxDBTimeFormat(value.get(i).toString());
if ("time".equals(fieldName)) {
field.set(obj, simpleDateFormat.format(new Date(time)));
} else {
field.set(obj, value.get(i));
}
}
}
} catch (NoSuchFieldException | SecurityException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
results.add(obj);
});
});
});
return results;
}
最后还有个问题,因为influxdb在插入数据的时候是按照纳秒计算的,那么我们转成毫秒后时间会有误差,所以我们在插入数据的时候手动给time字段赋值并设置按毫秒计算。
主要是这一段:
//手动给time字段赋值,并按毫秒进行计算
builder.time(times, TimeUnit.MILLISECONDS);
/**
* 批量新增,方法一
*/
public void insertBatchByRecords(List<?> records) {
long times = System.currentTimeMillis();
List<String> lines = new ArrayList<>();
records.forEach(record -> {
Class<?> clasz = record.getClass();
//获取度量
Measurement measurement = clasz.getAnnotation(Measurement.class);
//构建
Point.Builder builder = Point.measurement(measurement.name());
Field[] fieldArray = clasz.getDeclaredFields();
Column column = null;
for (Field field : fieldArray) {
try {
column = field.getAnnotation(Column.class);
//设置属性可操作
field.setAccessible(true);
if (column.tag()) {
//tag属性只能存储String类型
builder.tag(column.name(), field.get(record).toString());
} else {
//设置field
if (field.get(record) != null) {
Class<?> type = field.getType();
if (type == Long.class) {
builder.addField(column.name(), field.getLong(record));
} else if (type.equals(Double.class)) {
builder.addField(column.name(), Double.valueOf(field.get(record).toString()));
} else if (type == Float.class) {
builder.addField(column.name(), Float.valueOf(field.get(record).toString()));
} else {
builder.addField(column.name(), field.get(record).toString());
}
}
}
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
//手动给time字段赋值,并按毫秒进行计算
builder.time(times, TimeUnit.MILLISECONDS);
lines.add(builder.build().lineProtocol());
});
influxDB.write(lines);
}
那么在查询的时候就可以用时间戳来做查询条件,因为时间戳是毫秒值,而influxdb存储的时候是用的纳秒,所以在查询的时候得 毫秒值 * 1000000文章来源:https://www.toymoban.com/news/detail-464674.html
//构建查询语句,返回QueryResult
StringBuilder querySql = new StringBuilder("select * from tracer_angle where 1=1 ");
querySql.append(" and time >= ").append(startTime.getTime() * 1000000);
querySql.append(" and time <= ").append(endTime.getTime() * 1000000);
如果查询的时候用 毫秒值 * 1000000, 那么在数据插入时序库的时候一定要用下面这个手动给time字段赋值。文章来源地址https://www.toymoban.com/news/detail-464674.html
//手动给time字段赋值,并按毫秒进行计算
builder.time(times, TimeUnit.MILLISECONDS);
到了这里,关于Java集成influxDB 默认UTC时区问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!