第八节 时间处理(Time handling)

第八节 时间处理(Time handling)

libapr's time APIs are almost based on POSIX scheme. The value of apr_time_t is the elapsed time since UNIX epoch time(1970/1/1). The big differences are that apr_time_t is 64bit(long long) number and it represents microseconds. The most useful API is apr_time_now(). As you can guess, it returns the current time. You can find the protype declaration in apr_time.h.

APR时间API是基于POSIX方案的,是一个从1970年1月1日到现在的值,通以往的时间戳不一样的是apr_time_t是64位的正数它代表从1970年1月1日至今经过的微秒数。最长用的API是apr_time_now(),正如你预测的一样这个API返回的是当前时间,你可以在apr_time.h文件中找到他的原型声明。

/* excerpted from apr_time.h */
APR_DECLARE(apr_time_t) apr_time_now(void);

In many cases, we need to convert apr_time_t value to the other formats. There are mainly two formats. - apr_time_exp_t (time structure) - string formats (e.g. rfc822)

许多情况下,我们需要将apr_time_t类型的值转换成其他的格式。有两种常用的格式,apr_time_exp_t(另一种时间结构),字符串格式。

We use the following APIs to convert apr_time_t to apr_time_exp_t structure.

我们可以使用如下API将apr_time_t转换成apr_time_exp_t结构。

/* excerpted from apr_time.h */
APR_DECLARE(apr_status_t) apr_time_exp_gmt(apr_time_exp_t *result, apr_time_t input);
APR_DECLARE(apr_status_t) apr_time_exp_lt(apr_time_exp_t *result, apr_time_t input);

The apr_time_exp_gmt() returns the result in GMT timezone, and apr_time_exp_lt() returns the result in local timezone. The first argument of both APIs is result argument.

apr_time_exp_gmt()返回的一个GMT时区的apr_time_exp_t的结果,而apr_time_exp_lt()返回一个本地的时区的apr_time_exp_t的结果,第一个参数都是结果参数。

We can do the opposite conversion. We use the following API to convert apr_time_exp_t structure to apr_time_t value.

我们也可以使用下面的API将apr_time_exp_t结构的值转换成apr_time_t结构的值。

/* excerpted from apr_time.h */
APR_DECLARE(apr_status_t) apr_time_exp_get(apr_time_t *result, apr_time_exp_t *input);

There are some APIs to convert apr_time_t to various string formats as follows:

这里有一些API可以将apr_time_t转换成不同格式的字符串,API如下:

/* excerpted from apr_time.h */
APR_DECLARE(apr_status_t) apr_rfc822_date(char *date_str, apr_time_t t);
APR_DECLARE(apr_status_t) apr_ctime(char *date_str, apr_time_t t);
APR_DECLARE(apr_status_t) apr_strftime(char *s, apr_size_t *retsize, apr_size_t max, const char *format, apr_time_exp_t *tm);

On the other hand, if we convert such string formats to apr_time_t value, we have to call apr-util APIs, which are defined in apr_date.h.

另一方面我们可以将这些格式的字符串转换成apr_time_t类型的值,我们需要调用APR Util中的API,他们定义在apr_date.h文件中。

Please take a look at time-sample.c about the usage of time APIs.

具体使用方法请参照time-sample.c文件。

REMARK: As stated above, apr_time_t is long long type (64bit). Note that the following sample code causes overflow.

备注:如上所述,apr_time_t是一个64位长整型(long long),注意下面的代码导致的溢出。

/* BUGGY sample. This overflows */
const apr_time_t ONE_HOUR = 1000 * 1000 * 60 * 60;

We can fix the bug by explicit type cast, but I recommend you to use implicit type cast which libapr provides. The following code shows it.

我们直接通过类型转换解决这个Bug,但是我对推荐你使用APR提供的类型进行强制类型转换,代码如下:

/* two examples to get around overflow above */
const apr_time_t ONE_HOUR = APR_TIME_C(1000) * 1000 * 60 * 60;
or
const apr_time_t ONE_HOUR = APR_USEC_PER_SEC * 60 * 60;

REMARK: Sometimes, often in debugging, we want to print out time values. Unfortunately, Unix and Windows have different printf(3) format specifier for 64bit value. On Unix it is "%lld" and on Windows it is "%I64d". For such portability issues, libapr provides format specifiers, e.g. APR_INT64_T_FMT. There is APR_TIME_T_FMT in apr_time.h. We can write portable code with such format specifiers.

注意:经常在调试的时候,我们希望打印出时间的值,不幸的是在Unix和Windows中printf的64位的格式控制串(format specifier)有所不同,在Unix中它是“%lld”而在Windows中它是“%I64d”,处于移植性的考虑,APR提供了一些格式控制串,如APR_INT64_T_FMT,他被定义在apr_time.h文件中,我们在写可移植的代码时需要使用这样的格式控制串。

/* On Unix, APR_INT64_T_FMT is defined in apr.h */
#define APR_INT64_T_FMT "lld"
/* On Windows, APR_INT64_T_FMT is defined in apr.h */
#define APR_INT64_T_FMT "I64d"

/* excerpted from apr_time.h */
#define APR_TIME_T_FMT APR_INT64_T_FMT

/* We can use APR_TIME_T_FMT as follows */
printf("The current time: %" APR_TIME_T_FMT "[us]\n", apr_time_now());