时间语言支持

本页详细介绍了在 Fuchsia 上开发软件时如何应对时间。

一般来说,您可以使用适用于您所用语言的任何时间库。大多数库都可以与 Fuchsia 的 libc 实现链接以获取时间。建议您使用与平台无关的库,除非 您需要 Fuchsia 特定时间操作。

您可以选择多种时间选项,例如:

语言 Monotonic 世界协调时间 (UTC)
C clock_gettime time
C++ std::chrono::steady_clock std::chrono::system_clock
Rust std::time::Instant std::time::SystemTime

紫红色特定时间操作

在某些情况下,您需要以 Fuchsia 特定方式处理时间。这个 在需要直接处理 Fuchsia 的时间表示形式时,此方法是必需的, 或者当您需要处理 特定于 Fuchsia 的 UTC 行为

单调时间

Fuchsia 上的单调时间表示为一个 64 位有符号整数,其中包含系统开机以来经过的纳秒数。请参阅 如需了解详情,请访问 zx_clock_get_monotonic

单调时间可通过 libzircon 访问。

#include <stdio.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/clock.h>

void monotonic_examples(void) {
  // Read monotonic time.
  zx_time_t mono_nsec = zx_clock_get_monotonic();
  printf("The monotonic time is %ld ns.\n", mono_nsec);
}

C++

您可以通过 libzx 访问单调时间。

#include <lib/zx/clock.h>
#include <lib/zx/time.h>
#include <stdio.h>

void monotonic_examples() {
  // Read monotonic time.
  zx::time monotonic_time = zx::clock::get_monotonic();
  printf("The monotonic time is %ld ns.\n", monotonic_time.get());
}

Rust

您可以通过 zx crate 访问单调时间。此 crate 仅在树内可用。


pub fn monotonic_examples() {
    // Read monotonic time.
    let monotonic_time = zx::MonotonicInstant::get();
    println!("The monotonic time is {:?}.", monotonic_time);
}

UTC 时间

在 Fuchsia 上,世界协调时间 (UTC) 表示为一个有符号的 64 位整数,其中包含 从 Unix 纪元(1970 年 1 月 1 日)开始所经过的纳秒数。

基于 UTC 时钟的操作需要获取 UTC 时钟句柄 提供给运行时。

直接处理 UTC 时钟会启用一些特定于 Fuchsia 的操作, 包括:

  • 检查 UTC 时钟的属性。
  • 等待 UTC 时钟开始运行(表示已同步)后再读取。

C

您可以使用 zx_utc_reference_get 获取对 UTC 时钟的句柄,并使用 libzircon 中公开的系统调用。

#include <stdio.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/clock.h>
#include <zircon/utc.h>

void utc_examples(void) {
  // This is a borrowed handle. Do not close it, and do not replace it using
  // zx_utc_reference_swap while using it.
  zx_handle_t utc_clock = zx_utc_reference_get();

  if (utc_clock != ZX_HANDLE_INVALID) {
    // Wait for the UTC clock to start.  The clock may never start on a device
    // that does not have a RTC or a network connection.
    // A started clock may, but also may not have a valid UTC actual.
    zx_status_t status = zx_object_wait_one(utc_clock, ZX_CLOCK_STARTED, ZX_TIME_INFINITE, NULL);
    if (status == ZX_OK) {
      printf("UTC clock is started.\n");
    } else {
      printf("zx_object_wait_one syscall failed (status = %d).\n", status);
    }

    // Wait for the UTC clock to be externally synchronized.  Once that happens,
    // the clock is known to correspond to UTC actual (with error bounds available through
    // zx_clock_get_details).
    status = zx_object_wait_one(utc_clock, ZX_USER_SIGNAL_0, ZX_TIME_INFINITE, NULL);
    if (status == ZX_OK) {
      printf("UTC clock is externally synchronized.\n");
    } else {
      printf("zx_object_wait_one syscall failed (status = %d).\n", status);
    }

    // Wait for the UTC clock to be of "logging quality".  Logging quality UTC
    // clock is started, but not necessarily corresponding to UTC actual. This
    // clock is to be used only for logging timestamps.
    status = zx_object_wait_one(utc_clock, ZX_USER_SIGNAL_1, ZX_TIME_INFINITE, NULL);
    if (status == ZX_OK) {
      printf("UTC clock is of logging quality.\n");
    } else {
      printf("zx_object_wait_one syscall failed (status = %d).\n", status);
    }

    // Read the UTC clock.
    zx_time_t nsec;
    status = zx_clock_read(utc_clock, &nsec);
    if (status == ZX_OK) {
      printf("It has been %ld ns since the epoch.\n", nsec);
    } else {
      printf("zx_clock_read syscall failed (status = %d).\n", status);
    }

    // Read UTC clock details.
    zx_clock_details_v1_t details;
    status = zx_clock_get_details(utc_clock, ZX_CLOCK_ARGS_VERSION(1), &details);
    if (status == ZX_OK) {
      printf("The UTC clock's backstop time is %ld ns since the epoch.\n", details.backstop_time);
    } else {
      printf("zx_clock_get_details failed (status = %d).\n", status);
    }

  } else {
    printf("Error, our runtime has no clock assigned to it!\n");
  }
}

C++

您可以使用 zx_utc_reference_get 获取对 UTC 时钟的句柄,并使用 libzx 中的系统调用封装容器。

#include <lib/zx/clock.h>
#include <lib/zx/time.h>
#include <stdio.h>
#include <zircon/utc.h>

void utc_examples() {
  // This is a borrowed handle. Do not close it, and do not replace it using
  // zx_utc_reference_swap while using it.
  zx_handle_t utc_clock_handle = zx_utc_reference_get();
  zx::unowned_clock utc_clock(utc_clock_handle);

  // Wait for the UTC clock to start.  The clock may never start on a device
  // that does not have a RTC or a network connection.
  // A started clock may, but also may not have a valid UTC actual.
  zx_status_t status = utc_clock->wait_one(ZX_CLOCK_STARTED, zx::time::infinite(), nullptr);
  if (status == ZX_OK) {
    printf("UTC clock is started.\n");
  } else {
    printf("Waiting for the UTC clock to start failed (status = %d).\n", status);
  }

  // Wait for the UTC clock to be externally synchronized.  Once that happens,
  // the clock is known to correspond to UTC actual (with error bounds available through
  // `zx::Clock::get_details`).
  status = utc_clock->wait_one(ZX_USER_SIGNAL_0, zx::time::infinite(), nullptr);
  if (status == ZX_OK) {
    printf("UTC clock is externally synchronized.\n");
  } else {
    printf("Waiting for the UTC clock to start failed (status = %d).\n", status);
  }

  // Wait for the UTC clock to be of "logging quality".  Logging quality UTC
  // clock is started, but not necessarily corresponding to UTC actual. This
  // clock is to be used only for logging timestamps.
  status = utc_clock->wait_one(ZX_USER_SIGNAL_1, zx::time::infinite(), nullptr);
  if (status == ZX_OK) {
    printf("UTC clock is of logging quality.");
  } else {
    printf("zx_object_wait_one syscall failed (status = %d).\n", status);
  }

  // Read the UTC clock.
  zx_time_t utc_time;
  status = utc_clock->read(&utc_time);
  if (status == ZX_OK) {
    printf("The UTC time is %ld ns since the epoch\n", utc_time);
  } else {
    printf("Reading the UTC clock failed (status = %d).\n", status);
  }

  // Read clock details.
  zx_clock_details_v1_t details;
  status = utc_clock->get_details(&details);
  if (status == ZX_OK) {
    printf("The UTC clock's backstop time is %ld ns since the epoch.\n", details.backstop_time);
  } else {
    printf("Reading the UTC clock details failed (status = %d).\n", status);
  }
}

Rust

您可以使用 fuchsia_runtime crate 获取对 UTC 时钟的句柄,并使用 zx crate 中的系统调用封装容器。fuchsia_async crate 包含有助于等待时钟启动的实用程序。请注意,这些 crate 仅在树内可用。

use fuchsia_runtime::duplicate_utc_clock_handle;
use {fuchsia_async as fasync, zx};

pub async fn utc_examples() {
    // Obtain a UTC handle.
    let utc_clock = duplicate_utc_clock_handle(zx::Rights::SAME_RIGHTS)
        .expect("Failed to duplicate UTC clock handle.");

    // Wait for the UTC clock to start.  The clock may never start on a device
    // that does not have a RTC or a network connection.
    // A started clock may, but also may not have a valid UTC actual.
    fasync::OnSignals::new(&utc_clock, zx::Signals::CLOCK_STARTED)
        .await
        .expect("Failed to wait for ZX_CLOCK_STARTED.");
    println!("UTC clock is started.");

    // Wait for the UTC clock to be externally synchronized.  Once that happens,
    // the clock is known to correspond to UTC actual (with error bounds available through
    // `zx::Clock::get_details`).
    fasync::OnSignals::new(&utc_clock, zx::Signals::USER_0)
        .await
        .expect("Failed to wait for ZX_SIGNAL_USER_0.");
    println!("UTC clock is externally synchronized.");

    // Wait for the UTC clock to be of "logging quality".  Logging quality UTC
    // clock is started, but not necessarily corresponding to UTC actual. This
    // clock is to be used only for logging timestamps.
    fasync::OnSignals::new(&utc_clock, zx::Signals::USER_1)
        .await
        .expect("Failed to wait for ZX_SIGNAL_USER_1.");
    println!("UTC clock is of logging quality.");

    // Read the UTC clock.
    let utc_time = utc_clock.read().expect("Failed to read UTC clock.");
    println!("The UTC time is {:?}.", utc_time);

    // Read UTC clock details.
    let clock_details = utc_clock.get_details().expect("Failed to read UTC clock details.");
    println!("The UTC clock's backstop time is {:?}.", clock_details.backstop);
}