如何在Elasticsearch Painless语言中将毫秒转换为人类可读时长
Painless毫秒值转人类可读时长实现方案
报错原因
- 你尝试的旧方案使用了Painless沙箱环境禁止直接调用的Java时间类方法/外部类构造逻辑,Watcher运行上下文对Painless的权限限制比普通搜索脚本更严格,所以直接触发编译错误。
- 部分旧方案采用的Java 8 Duration类的格式化方法在低版本Elasticsearch的Painless中未被纳入允许调用的白名单。
可用的Painless实现代码
实现逻辑说明
直接通过算术运算拆分毫秒值到天、时、分、秒、毫秒维度,不需要依赖任何外部时间类,完全适配Painless沙箱限制,兼容所有支持Painless的ES版本,不会出现编译错误。
// 输入参数:millis = 需要转换的毫秒值,Long类型 long remaining = params.millis; long days = remaining / 86400000; remaining = remaining % 86400000; long hours = remaining / 3600000; remaining = remaining % 3600000; long minutes = remaining / 60000; remaining = remaining % 60000; long seconds = remaining / 1000; long milliseconds = remaining % 1000; // 拼接输出格式,可按需调整结构和单位 String readable = ""; if (days > 0) readable += days + "天"; if (hours > 0 || !readable.isEmpty()) readable += hours + "时"; if (minutes > 0 || !readable.isEmpty()) readable += minutes + "分"; if (seconds > 0 || !readable.isEmpty()) readable += seconds + "秒"; // 不需要展示毫秒可删除下一行 readable += milliseconds + "毫秒"; return readable;
输出示例
- 输入
1234567毫秒,输出为20分34秒567毫秒 - 输入
100234567毫秒,输出为1天3时50分34秒567毫秒
Watcher中调用示例
如果是在Watcher的condition或者transform中使用,直接把上述逻辑嵌入script块,参数从ctx中取对应毫秒字段即可,示例如下:
{ "script": { "source": """ long remaining = ctx.payload.task_duration; long days = remaining / 86400000; remaining %= 86400000; long hours = remaining / 3600000; remaining %= 3600000; long minutes = remaining / 60000; remaining %= 60000; long seconds = remaining / 1000; long ms = remaining % 1000; String res = ""; if (days>0) res += days+"天"; if (hours>0 || !res.isEmpty()) res += hours+"时"; if (minutes>0 || !res.isEmpty()) res += minutes+"分"; res += seconds + "秒" + ms + "毫秒"; return res; """, "lang": "painless" } }
内容的提问来源于stack exchange,提问作者l0b0
相关产品推荐
相关产品推荐

