18. ROS programming: time c++ in ROS

Table of contents

Get the current moment + set the specified moment (time point)

Create the time.cpp file

time.cpp

CMakeList.txt configuration

Compile + start ROS Master + run node

result:

duration (period)

Add duration part

compile + run node

Time operations (calculations of duration and time)

Add time calculation part

compile + run node

timer

Add timer section

compile + run node

Advanced use of timer

compile + run node

Reference learning materials: Zhao Xuzuo's courses at Station B

Get the current moment + set the specified moment (time point)

Create the time.cpp file

Because there is no representative function implemented, it is randomly placed under the src of a function package.

time.cpp

#include "ros/ros.h"
/*
    任务:获取当前时刻,设置指定时刻
    获取当前时刻:调用ros命名空间下的Time类下的now()函数.
    指定时刻:调用ros命名空间下的Time类,注意参数的配置,用逗号分割传入两个参数,前后两个参数为整形,前为秒,后为纳秒.
            用一个参数,为double型.
*/
int main(int argc, char *argv[])
{
    // 防止控制台中文乱码
    setlocale(LC_ALL,"");
    // 初始化节点
    ros::init(argc,argv,"demo_time");
    // 初始化句柄,此处会发现没用到n.但是我在注释掉初始化句柄后,就会出现无法调用api的错误.
    ros::NodeHandle n;
    // 获取当前时刻---now被调用的时刻.参考系:1970年1月1日00:00:00
    ros::Time right_now = ros::Time::now();
    // 打印在控制台终端,其中toSec()与sec是以秒的形式输出,但是注意返回的类,前者为double型,后者为int32
    ROS_INFO("当前时刻:%.2f",right_now.toSec());
    ROS_INFO("当前时刻:%d",right_now.sec);
    // 设置指定时刻:调用ros命名空间下的Time类,注意参数的配置,用逗号分割传入两个参数,前后两个参数为整形,前为秒,后为纳秒.传入一个参数,为double型.
    ros::Time t1(20,123456789);
    ros::Time t2(20.123456789);
    // 与前面相同转化为秒
    ROS_INFO("t1 = %.2f",t1.toSec());
    ROS_INFO("t2 = %.2f",t2.toSec());
    return 0;
}

Note 1: the type of incoming parameters and return parameters. Vscode can prompt the type of the incoming parameter through ctrl+shift+space, and the type of the returned parameter can be prompted by pointing the mouse at the function name.

Note 2: The initialization handle is not called from the program, but it must be initialized, otherwise the subsequent API cannot be called. If the handle is not initialized, the following error will be reported:

terminate called after throwing an instance of 'ros::TimeNotInitializedException' 
what():  Cannot use ros::Time::now() before the first NodeHandle has been created or ros::start() has been called.   If this is a standalone app or test that just uses ros::Time and does not communicate over ROS, you may also call ros::Time::init() 
已放弃 (核心已转储)

CMakeList.txt configuration

add_executable(time src/time.cpp)
add_dependencies(time ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(time
  ${catkin_LIBRARIES}
)

Compile + start ROS Master + run node

catkin_make
roscore

Note that I put it under the sub_pub function package. 

source ./devel/setup.bash 
rosrun sub_pub time

result:

rosmelodic@rosmelodic-virtual-machine:~/catkin_ws$ rosrun sub_pub time 
[ INFO] [1667180564.625914795]: 当前时刻:1667180564.63
[ INFO] [1667180564.626587019]: 当前时刻:1667180564
[ INFO] [1667180564.626614175]: t1 = 20.12
[ INFO] [1667180564.626632135]: t2 = 20.12

duration (period)

Add duration part

Continue with the previous file and make changes.

#include "ros/ros.h"
/*
    任务:获取当前时刻,设置指定时刻
    获取当前时刻:调用ros命名空间下的Time类下的now()函数.
    指定时刻:调用ros命名空间下的Time类,注意参数的配置,用逗号分割传入两个参数,前后两个参数为整形,前为秒,后为纳秒.
            用一个参数,为double型.
*/
int main(int argc, char *argv[])
{
    // 防止控制台中文乱码
    setlocale(LC_ALL,"");
    // 初始化节点
    ros::init(argc,argv,"demo_time");
    // 初始化句柄,此处会发现没用到n.但是我在注释掉初始化句柄后,就会出现无法调用api的错误.
    ros::NodeHandle n;
    // 获取当前时刻---now被调用的时刻.参考系:1970年1月1日00:00:00
    ros::Time right_now = ros::Time::now();
    // 打印在控制台终端,其中toSec()与sec是以秒的形式输出,但是注意返回的类,前者为double型,后者为int32
    ROS_INFO("当前时刻:%.2f",right_now.toSec());
    ROS_INFO("当前时刻:%d",right_now.sec);
    // 设置指定时刻:调用ros命名空间下的Time类,注意参数的配置,用逗号分割传入两个参数,前后两个参数为整形,前为秒,后为纳秒.传入一个参数,为double型.
    ros::Time t1(20,123456789);
    ros::Time t2(20.123456789);
    // 与前面相同转化为秒
    ROS_INFO("t1 = %.2f",t1.toSec());
    ROS_INFO("t2 = %.2f",t2.toSec());
    // 持续时间部分
    ros::Time start_time = ros::Time::now();
    ROS_INFO("开始时刻:%.2f",start_time.toSec());
    //持续10.12秒钟,参数是double类型的,以秒为单位
    ros::Duration du(10.12);
    //按照指定的持续时间休眠
    du.sleep();
    // 结束时间
    ros::Time end_time = ros::Time::now();
    ROS_INFO("结束时刻:%.2f",end_time.toSec());
    // 二者只差
    ROS_INFO("结束时刻与开始时刻的差值:%.2f",end_time.toSec()-start_time.toSec());
    // 持续时间
    ROS_INFO("持续时间:%.2f",du.toSec());
    return 0;
}

Critical section duration section:

    // 持续时间部分
    ros::Time start_time = ros::Time::now();
    ROS_INFO("开始时刻:%.2f",start_time.toSec());
    //持续10.12秒钟,参数是double类型的,以秒为单位
    ros::Duration du(10.12);
    //按照指定的持续时间休眠
    du.sleep();
    // 结束时间
    ros::Time end_time = ros::Time::now();
    ROS_INFO("结束时刻:%.2f",end_time.toSec());
    // 二者只差
    ROS_INFO("结束时刻与开始时刻的差值:%.2f",end_time.toSec()-start_time.toSec());
    // 持续时间
    ROS_INFO("持续时间:%.2f",du.toSec());

compile + run node

rosmelodic@rosmelodic-virtual-machine:~/catkin_ws$ rosrun sub_pub time 
[ INFO] [1667189818.039882979]: 当前时刻:1667189818.04
[ INFO] [1667189818.040486028]: 当前时刻:1667189818
[ INFO] [1667189818.040516457]: t1 = 20.12
[ INFO] [1667189818.040554559]: t2 = 20.12
[ INFO] [1667189818.040562453]: 开始时刻:1667189818.04
[ INFO] [1667189828.160898726]: 结束时刻:1667189828.16
[ INFO] [1667189828.160960446]: 结束时刻与开始时刻的差值:10.12
[ INFO] [1667189828.160978014]: 持续时间:10.12

The result is as expected, the difference is equal to the duration.

Time operations (calculations of duration and time)

Add time calculation part

#include "ros/ros.h"
/*
    任务:获取当前时刻,设置指定时刻
    获取当前时刻:调用ros命名空间下的Time类下的now()函数.
    指定时刻:调用ros命名空间下的Time类,注意参数的配置,用逗号分割传入两个参数,前后两个参数为整形,前为秒,后为纳秒.
            用一个参数,为double型.
*/
int main(int argc, char *argv[])
{
    // 防止控制台中文乱码
    setlocale(LC_ALL,"");
    // 初始化节点
    ros::init(argc,argv,"demo_time");
    // 初始化句柄,此处会发现没用到n.但是我在注释掉初始化句柄后,就会出现无法调用api的错误.
    ros::NodeHandle n;
    // 获取当前时刻---now被调用的时刻.参考系:1970年1月1日00:00:00
    ros::Time right_now = ros::Time::now();
    // 打印在控制台终端,其中toSec()与sec是以秒的形式输出,但是注意返回的类,前者为double型,后者为int32
    ROS_INFO("当前时刻:%.2f",right_now.toSec());
    ROS_INFO("当前时刻:%d",right_now.sec);
    // 设置指定时刻:调用ros命名空间下的Time类,注意参数的配置,用逗号分割传入两个参数,前后两个参数为整形,前为秒,后为纳秒.传入一个参数,为double型.
    ros::Time t1(20,123456789);
    ros::Time t2(20.123456789);
    // 与前面相同转化为秒
    ROS_INFO("t1 = %.2f",t1.toSec());
    ROS_INFO("t2 = %.2f",t2.toSec());
    // 持续时间部分
    ros::Time start_time = ros::Time::now();
    ROS_INFO("开始时刻:%.2f",start_time.toSec());
    //持续10.12秒钟,参数是double类型的,以秒为单位
    ros::Duration du(10.12);
    //按照指定的持续时间休眠
    du.sleep();
    // 结束时间
    ros::Time end_time = ros::Time::now();
    ROS_INFO("结束时刻:%.2f",end_time.toSec());
    // 二者只差
    ROS_INFO("结束时刻与开始时刻的差值:%.2f",end_time.toSec()-start_time.toSec());
    // 持续时间
    ROS_INFO("持续时间:%.2f",du.toSec());
    // 持续时间与时刻运算
    // 持续时间为5秒
    ros::Duration du1(5);
    // 开始时间为当前时间
    ros::Time kaishi_time = ros::Time::now();
    // 这样是不行的.
    // ROS_INFO("开始时刻加上持续时间:%.2f",kaishi_time + du1);
    // 停止时间
    ros::Time stop_time = kaishi_time + du1;
    ROS_INFO("开始时刻加上持续时间测试1:%.2f",stop_time.toSec());
    ROS_INFO("开始时刻加上持续时间测试2:%.2f",kaishi_time.toSec()+ du1.toSec());
    // 时刻与时刻运算
    // 错误操作展示
    // 不存在用户定义的从 "ros::Duration" 到 "ros::Time" 的适当转换
    // ros::Time du2 = stop_time - kaishi_time;
    // 操作数类型为: ros::Time + ros::Time,没有与这些操作数匹配的 "+" 运算符
    // ros::Time du2 = stop_time + kaishi_time;
    ros::Duration du2 = stop_time - kaishi_time;
    ROS_INFO("时刻相减:%.2f",du2.toSec());
    // 持续时间与持续时间计算
    ros::Duration du3(1);
    ros::Duration du4(2);
    ros::Duration du5 = du3 + du4;
    ROS_INFO("持续时间相加:%.2f",du5.toSec());
    return 0;
}

Important section

    // 持续时间与时刻运算
    // 持续时间为5秒
    ros::Duration du1(5);
    // 开始时间为当前时间
    ros::Time kaishi_time = ros::Time::now();
    // 这样是不行的.
    // ROS_INFO("开始时刻加上持续时间:%.2f",kaishi_time + du1);
    // 停止时间
    ros::Time stop_time = kaishi_time + du1;
    ROS_INFO("开始时刻加上持续时间测试1:%.2f",stop_time.toSec());
    ROS_INFO("开始时刻加上持续时间测试2:%.2f",kaishi_time.toSec()+ du1.toSec());
    // 时刻与时刻运算
    // 错误操作展示
    // 不存在用户定义的从 "ros::Duration" 到 "ros::Time" 的适当转换
    // ros::Time du2 = stop_time - kaishi_time;
    // 操作数类型为: ros::Time + ros::Time,没有与这些操作数匹配的 "+" 运算符
    // ros::Time du2 = stop_time + kaishi_time;
    ros::Duration du2 = stop_time - kaishi_time;
    ROS_INFO("时刻相减:%.2f",du2.toSec());
    // 持续时间与持续时间计算
    ros::Duration du3(1);
    ros::Duration du4(2);
    ros::Duration du5 = du3 + du4;
    ROS_INFO("持续时间相加:%.2f",du5.toSec());

compile + run node

rosmelodic@rosmelodic-virtual-machine:~/catkin_ws$ rosrun sub_pub time 
[ INFO] [1667191706.440051413]: 当前时刻:1667191706.44
[ INFO] [1667191706.440597798]: 当前时刻:1667191706
[ INFO] [1667191706.440616560]: t1 = 20.12
[ INFO] [1667191706.440633713]: t2 = 20.12
[ INFO] [1667191706.440640151]: 开始时刻:1667191706.44
[ INFO] [1667191716.560760176]: 结束时刻:1667191716.56
[ INFO] [1667191716.560813883]: 结束时刻与开始时刻的差值:10.12
[ INFO] [1667191716.560820124]: 持续时间:10.12
[ INFO] [1667191716.560828471]: 开始时刻加上持续时间测试1:1667191721.56
[ INFO] [1667191716.560838710]: 开始时刻加上持续时间测试2:1667191721.56
[ INFO] [1667191716.560847785]: 时刻相减:5.00
[ INFO] [1667191716.560852309]: 持续时间相加:3.00

timer

Add timer section

#include "ros/ros.h"
/*
    任务:获取当前时刻,设置指定时刻
    获取当前时刻:调用ros命名空间下的Time类下的now()函数.
    指定时刻:调用ros命名空间下的Time类,注意参数的配置,用逗号分割传入两个参数,前后两个参数为整形,前为秒,后为纳秒.
            用一个参数,为double型.
*/

void huidiao(const ros::TimerEvent& event){
    ROS_INFO("----两秒一次----");
}

int main(int argc, char *argv[])
{
    // 防止控制台中文乱码
    setlocale(LC_ALL,"");
    // 初始化节点
    ros::init(argc,argv,"demo_time");
    // 初始化句柄,此处会发现没用到n.但是我在注释掉初始化句柄后,就会出现无法调用api的错误.
    ros::NodeHandle n;
    // 获取当前时刻---now被调用的时刻.参考系:1970年1月1日00:00:00
    ros::Time right_now = ros::Time::now();
    // 打印在控制台终端,其中toSec()与sec是以秒的形式输出,但是注意返回的类,前者为double型,后者为int32
    ROS_INFO("当前时刻:%.2f",right_now.toSec());
    ROS_INFO("当前时刻:%d",right_now.sec);
    // 设置指定时刻:调用ros命名空间下的Time类,注意参数的配置,用逗号分割传入两个参数,前后两个参数为整形,前为秒,后为纳秒.传入一个参数,为double型.
    ros::Time t1(20,123456789);
    ros::Time t2(20.123456789);
    // 与前面相同转化为秒
    ROS_INFO("t1 = %.2f",t1.toSec());
    ROS_INFO("t2 = %.2f",t2.toSec());
    // 持续时间部分
    ros::Time start_time = ros::Time::now();
    ROS_INFO("开始时刻:%.2f",start_time.toSec());
    //持续10.12秒钟,参数是double类型的,以秒为单位
    ros::Duration du(10.12);
    //按照指定的持续时间休眠
    du.sleep();
    // 结束时间
    ros::Time end_time = ros::Time::now();
    ROS_INFO("结束时刻:%.2f",end_time.toSec());
    // 二者只差
    ROS_INFO("结束时刻与开始时刻的差值:%.2f",end_time.toSec()-start_time.toSec());
    // 持续时间
    ROS_INFO("持续时间:%.2f",du.toSec());
    // 持续时间与时刻运算
    // 持续时间为5秒
    ros::Duration du1(5);
    // 开始时间为当前时间
    ros::Time kaishi_time = ros::Time::now();
    // 这样是不行的.
    // ROS_INFO("开始时刻加上持续时间:%.2f",kaishi_time + du1);
    // 停止时间
    ros::Time stop_time = kaishi_time + du1;
    ROS_INFO("开始时刻加上持续时间测试1:%.2f",stop_time.toSec());
    ROS_INFO("开始时刻加上持续时间测试2:%.2f",kaishi_time.toSec()+ du1.toSec());
    // 时刻与时刻运算
    // 错误操作展示
    // 不存在用户定义的从 "ros::Duration" 到 "ros::Time" 的适当转换
    // ros::Time du2 = stop_time - kaishi_time;
    // 操作数类型为: ros::Time + ros::Time,没有与这些操作数匹配的 "+" 运算符
    // ros::Time du2 = stop_time + kaishi_time;
    ros::Duration du2 = stop_time - kaishi_time;
    ROS_INFO("时刻相减:%.2f",du2.toSec());
    // 持续时间与持续时间计算
    ros::Duration du3(1);
    ros::Duration du4(2);
    ros::Duration du5 = du3 + du4;
    ROS_INFO("持续时间相加:%.2f",du5.toSec());
    // 定时器部分,实现与ros::Rate类似的效果
    // ros::Timer createTimer(ros::Duration period, 
    //     const ros::TimerCallback &callback, 
    //     bool oneshot = false, 
    //     bool autostart = true) const
    ros::Timer timer = n.createTimer(ros::Duration(2), huidiao);
    ros::spin();
    return 0;
}

Important section

void huidiao(const ros::TimerEvent& event){
    ROS_INFO("----两秒一次----");
}
    ros::NodeHandle n;
    // 定时器部分,实现与ros::Rate类似的效果
    // ros::Timer createTimer(ros::Duration period, 
    //     const ros::TimerCallback &callback, 
    //     bool oneshot = false, 
    //     bool autostart = true) const
    ros::Timer timer = n.createTimer(ros::Duration(2), huidiao);
    ros::spin();

Points to note When encountering a callback function, you must remember to return to the function, and don't forget to initialize the handle. Through the above study, we can know that if you don’t know whether to add an initialization handle or not, you can choose to add an initialization handle. Even if you don’t call it, the api in the program may be used, and when it is used, you don’t need to initialize the handle again, just call it directly. Can.

compile + run node

rosmelodic@rosmelodic-virtual-machine:~/catkin_ws$ rosrun sub_pub time 
[ INFO] [1667194649.765253594]: 当前时刻:1667194649.77
[ INFO] [1667194649.766513119]: 当前时刻:1667194649
[ INFO] [1667194649.766554905]: t1 = 20.12
[ INFO] [1667194649.766559855]: t2 = 20.12
[ INFO] [1667194649.766577168]: 开始时刻:1667194649.77
[ INFO] [1667194659.886981567]: 结束时刻:1667194659.89
[ INFO] [1667194659.887036503]: 结束时刻与开始时刻的差值:10.12
[ INFO] [1667194659.887042017]: 持续时间:10.12
[ INFO] [1667194659.887049563]: 开始时刻加上持续时间测试1:1667194664.89
[ INFO] [1667194659.887076444]: 开始时刻加上持续时间测试2:1667194664.89
[ INFO] [1667194659.887081739]: 时刻相减:5.00
[ INFO] [1667194659.887085717]: 持续时间相加:3.00
[ INFO] [1667194661.888278373]: ----两秒一次----
[ INFO] [1667194663.887925384]: ----两秒一次----
[ INFO] [1667194665.887802243]: ----两秒一次----
[ INFO] [1667194667.887758576]: ----两秒一次----
[ INFO] [1667194669.887829379]: ----两秒一次----

The expected result is achieved. It can be seen that in the timer part, the same function as ros::Rate is realized. The loop part is placed in the callback function, and the callback function is continuously looped through the return function. The delay part uses ros::Duration() to give a delay time in seconds.

Advanced use of timer

#include "ros/ros.h"
/*
    任务:获取当前时刻,设置指定时刻
    获取当前时刻:调用ros命名空间下的Time类下的now()函数.
    指定时刻:调用ros命名空间下的Time类,注意参数的配置,用逗号分割传入两个参数,前后两个参数为整形,前为秒,后为纳秒.
            用一个参数,为double型.
*/

void huidiao(const ros::TimerEvent& event){
    // ROS_INFO("----两秒一次----");
    // float
    ROS_INFO("调用的时刻float:%.2f",event.current_real.toSec());
    // string
    ROS_INFO("调用的时刻string:%s",std::to_string(event.current_real.toSec()).c_str());
}

int main(int argc, char *argv[])
{
    // 防止控制台中文乱码
    setlocale(LC_ALL,"");
    // 初始化节点
    ros::init(argc,argv,"demo_time");
    // 初始化句柄,此处会发现没用到n.但是我在注释掉初始化句柄后,就会出现无法调用api的错误.
    ros::NodeHandle n;
    // 获取当前时刻---now被调用的时刻.参考系:1970年1月1日00:00:00
    ros::Time right_now = ros::Time::now();
    // 打印在控制台终端,其中toSec()与sec是以秒的形式输出,但是注意返回的类,前者为double型,后者为int32
    ROS_INFO("当前时刻:%.2f",right_now.toSec());
    ROS_INFO("当前时刻:%d",right_now.sec);
    // 设置指定时刻:调用ros命名空间下的Time类,注意参数的配置,用逗号分割传入两个参数,前后两个参数为整形,前为秒,后为纳秒.传入一个参数,为double型.
    ros::Time t1(20,123456789);
    ros::Time t2(20.123456789);
    // 与前面相同转化为秒
    ROS_INFO("t1 = %.2f",t1.toSec());
    ROS_INFO("t2 = %.2f",t2.toSec());
    // 持续时间部分
    ros::Time start_time = ros::Time::now();
    ROS_INFO("开始时刻:%.2f",start_time.toSec());
    //持续10.12秒钟,参数是double类型的,以秒为单位
    ros::Duration du(10.12);
    //按照指定的持续时间休眠
    du.sleep();
    // 结束时间
    ros::Time end_time = ros::Time::now();
    ROS_INFO("结束时刻:%.2f",end_time.toSec());
    // 二者只差
    ROS_INFO("结束时刻与开始时刻的差值:%.2f",end_time.toSec()-start_time.toSec());
    // 持续时间
    ROS_INFO("持续时间:%.2f",du.toSec());
    ROS_INFO("持续时间:%.2f",ros::Duration(11).toSec());
    // 持续时间与时刻运算
    // 持续时间为5秒
    ros::Duration du1(5);
    // 开始时间为当前时间
    ros::Time kaishi_time = ros::Time::now();
    // 这样是不行的.
    // ROS_INFO("开始时刻加上持续时间:%.2f",kaishi_time + du1);
    // 停止时间
    ros::Time stop_time = kaishi_time + du1;
    ROS_INFO("开始时刻加上持续时间测试1:%.2f",stop_time.toSec());
    ROS_INFO("开始时刻加上持续时间测试2:%.2f",kaishi_time.toSec()+ du1.toSec());
    // 时刻与时刻运算
    // 错误操作展示
    // 不存在用户定义的从 "ros::Duration" 到 "ros::Time" 的适当转换
    // ros::Time du2 = stop_time - kaishi_time;
    // 操作数类型为: ros::Time + ros::Time,没有与这些操作数匹配的 "+" 运算符
    // ros::Time du2 = stop_time + kaishi_time;
    ros::Duration du2 = stop_time - kaishi_time;
    ROS_INFO("时刻相减:%.2f",du2.toSec());
    // 持续时间与持续时间计算
    ros::Duration du3(1);
    ros::Duration du4(2);
    ros::Duration du5 = du3 + du4;
    ROS_INFO("持续时间相加:%.2f",du5.toSec());
    // 定时器部分,实现与ros::Rate类似的效果
    // ros::Timer createTimer(ros::Duration period, 
    //     const ros::TimerCallback &callback, 
    //     bool oneshot = false, 
    //     bool autostart = true) const
    // ros::Timer timer = n.createTimer(ros::Duration(2), huidiao);
    // 进阶操作,循环一次同时不自动启动,采用手动启动
    ros::Timer timer = n.createTimer(ros::Duration(2), huidiao, true, false);
    timer.start();
    ros::spin();
    return 0;
}

Important section:

 Added the conversion of strings, note that strings must be converted to c language strings with c_str()

void huidiao(const ros::TimerEvent& event){
    // ROS_INFO("----两秒一次----");
    // float
    ROS_INFO("调用的时刻float:%.2f",event.current_real.toSec());
    // string
    ROS_INFO("调用的时刻string:%s",std::to_string(event.current_real.toSec()).c_str());
}
    ros::NodeHandle n;

 Timer: official code hints

ros::Timer createTimer(ros::Duration period, const ros::TimerCallback &callback, bool oneshot = false, bool autostart = true) const

 Loop once without autostarting.

    ros::Timer timer = n.createTimer(ros::Duration(2), huidiao, true, false);
    timer.start();
    ros::spin();

compile + run node

rosmelodic@rosmelodic-virtual-machine:~/catkin_ws$ rosrun sub_pub time 
[ INFO] [1667196970.287954775]: 当前时刻:1667196970.29
[ INFO] [1667196970.288547309]: 当前时刻:1667196970
[ INFO] [1667196970.288569537]: t1 = 20.12
[ INFO] [1667196970.288573954]: t2 = 20.12
[ INFO] [1667196970.288578463]: 开始时刻:1667196970.29
[ INFO] [1667196980.409242802]: 结束时刻:1667196980.41
[ INFO] [1667196980.409300465]: 结束时刻与开始时刻的差值:10.12
[ INFO] [1667196980.409319424]: 持续时间:10.12
[ INFO] [1667196980.409328130]: 持续时间:11.00
[ INFO] [1667196980.409346808]: 开始时刻加上持续时间测试1:1667196985.41
[ INFO] [1667196980.409371731]: 开始时刻加上持续时间测试2:1667196985.41
[ INFO] [1667196980.409388619]: 时刻相减:5.00
[ INFO] [1667196980.409393265]: 持续时间相加:3.00
[ INFO] [1667196982.409913397]: 调用的时刻float:1667196982.41
[ INFO] [1667196982.409964732]: 调用的时刻string:1667196982.409868

おすすめ

転載: blog.csdn.net/wzfafabga/article/details/127609516