1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
/*!
# build-time
Simple proc-macros to generate build timestamp string literals.
Based on Jasen Borisov's [build_timestamp](https://crates.io/crates/build_timestamp) crate.
Two function like procedures are provided: `build_time_utc` and `build_time_local`.
They take an optional [`strftime`](https://docs.rs/chrono/0.4/chrono/format/strftime/index.html)
date and time format string as input, and return a string literal.
If the input is empty, they will return a string literal in
[RFC 3339 date and time format](https://en.wikipedia.org/wiki/ISO_8601#RFCs),
e.g., `"2021-05-29T06:55:50.418437046+00:00"`.
Requires Rust 1.45+ because these macros are used in expression positions.
## Usage
```rust
use build_time::{build_time_utc, build_time_local};
// Returns the UTC build timestamp in RFC3339 date and time format.
let utc_build_time = build_time_utc!();
// Returns the local build timestamp in the specified format.
let local_build_time = build_time_local!("%Y-%m-%dT%H:%M:%S%.f%:z");
```
*/
use chrono::{DateTime, Local, Utc};
use once_cell::sync::Lazy;
use proc_macro::TokenStream;
use proc_macro2::Span;
use quote::quote;
use syn::{parse_macro_input, LitStr};
static BUILD_TIME: Lazy<DateTime<Utc>> = Lazy::new(Utc::now);
/// Build time in UTC.
///
/// It takes an optional [`strftime`](https://docs.rs/chrono/0.4/chrono/format/strftime/index.html)
/// date and time format string as input, and returns a string literal.
/// If the input is empty, it will return a string literal in
/// [RFC 3339 date and time format](https://en.wikipedia.org/wiki/ISO_8601#RFCs),
/// e.g., `"2021-05-29T06:55:50.418437046+00:00"`.
///
/// # Example
///
/// ```rust
/// use build_time::build_time_utc;
///
/// // Returns the UTC build timestamp in RFC3339 date and time format.
/// let build_time_rfc3339 = build_time_utc!();
///
/// // Returns the UTC build timestamp in the specified format.
/// let build_time_formatted = build_time_utc!("%Y-%m-%dT%H:%M:%S%.f%:z");
/// ```
#[proc_macro]
pub fn build_time_utc(input: TokenStream) -> TokenStream {
let time_str = if input.is_empty() {
BUILD_TIME.to_rfc3339()
} else {
let format = parse_macro_input!(input as LitStr);
BUILD_TIME.format(&format.value()).to_string()
};
let lit = LitStr::new(&time_str, Span::call_site());
quote!(#lit).into()
}
/// Build time in the local timescale.
///
/// It takes an optional [`strftime`](https://docs.rs/chrono/0.4/chrono/format/strftime/index.html)
/// date and time format string as input, and returns a string literal.
/// If the input is empty, it will return a string literal in
/// [RFC 3339 date and time format](https://en.wikipedia.org/wiki/ISO_8601#RFCs),
/// e.g., `"2021-05-29T06:55:50.418437046+00:00"`.
///
/// # Example
///
/// ```rust
/// use build_time::build_time_local;
///
/// // Returns the local build timestamp in RFC3339 date and time format.
/// let build_time_rfc3339 = build_time_local!();
///
/// // Returns the local build timestamp in the specified format.
/// let build_time_formatted = build_time_local!("%Y-%m-%dT%H:%M:%S%.f%:z");
/// ```
#[proc_macro]
pub fn build_time_local(input: TokenStream) -> TokenStream {
let local_time = BUILD_TIME.with_timezone(&Local);
let time_str = if input.is_empty() {
local_time.to_rfc3339()
} else {
let format = parse_macro_input!(input as LitStr);
local_time.format(&format.value()).to_string()
};
let lit = LitStr::new(&time_str, Span::call_site());
quote!(#lit).into()
}