@@ -7,12 +7,16 @@ use std::str::FromStr;
77
88use crate :: endpoints:: tasks:: task_query_builder:: { TaskQuery , TaskReport } ;
99use crate :: endpoints:: tasks:: { is_a_tag, is_tag_keyword} ;
10- use chrono:: { DateTime , TimeDelta } ;
10+ use chrono:: { DateTime , TimeDelta , Utc } ;
1111use rand:: distr:: { Alphanumeric , SampleString } ;
1212use serde:: { de, Deserialize , Deserializer , Serialize } ;
1313use taskchampion:: Uuid ;
1414use tera:: Context ;
1515use tracing:: warn;
16+ #[ cfg( test) ]
17+ mod tests;
18+ #[ cfg( test) ]
19+ use chrono:: TimeZone ;
1620
1721lazy_static:: lazy_static! {
1822 pub static ref TEMPLATES : tera:: Tera = {
@@ -26,6 +30,7 @@ lazy_static::lazy_static! {
2630 tera. register_function( "project_name" , get_project_name_link( ) ) ;
2731 tera. register_function( "date_proper" , get_date_proper( ) ) ;
2832 tera. register_function( "timer_value" , get_timer( ) ) ;
33+ tera. register_function( "datetime_iso" , get_datetime_iso( ) ) ;
2934 tera. register_function( "date" , get_date( ) ) ;
3035 tera. register_function( "obj" , obj( ) ) ;
3136 tera. register_function( "remove_project_tag" , remove_project_from_tag( ) ) ;
@@ -303,6 +308,17 @@ fn update_tag_bar_key_comb() -> impl tera::Filter {
303308 )
304309}
305310
311+ #[ cfg( not( test) ) ]
312+ #[ allow( dead_code) ]
313+ fn get_utc_now ( ) -> DateTime < Utc > {
314+ chrono:: prelude:: Utc :: now ( )
315+ }
316+ #[ cfg( test) ]
317+ #[ allow( dead_code) ]
318+ fn get_utc_now ( ) -> DateTime < Utc > {
319+ chrono:: Utc . with_ymd_and_hms ( 2025 , 5 , 1 , 3 , 55 , 0 ) . unwrap ( )
320+ }
321+
306322pub struct DeltaNow {
307323 pub now : DateTime < chrono:: Utc > ,
308324 pub delta : TimeDelta ,
@@ -317,7 +333,7 @@ impl DeltaNow {
317333 chrono:: prelude:: NaiveDateTime :: parse_from_str ( time, "%Y-%m-%dT%H:%M:%SZ" ) . unwrap ( )
318334 )
319335 . and_utc ( ) ;
320- let now = chrono :: prelude :: Utc :: now ( ) ;
336+ let now = get_utc_now ( ) ;
321337 let delta = now - time;
322338 Self { now, delta, time }
323339 }
@@ -361,6 +377,22 @@ fn get_date_proper() -> impl tera::Function {
361377 )
362378}
363379
380+ fn get_datetime_iso ( ) -> impl tera:: Function {
381+ Box :: new (
382+ move |args : & HashMap < String , tera:: Value > | -> tera:: Result < tera:: Value > {
383+ let date_time_str = args. get ( "datetime" ) . unwrap ( ) . as_str ( ) . unwrap ( ) ;
384+ // we are working with utc time
385+ let date_time = chrono:: prelude:: NaiveDateTime :: parse_from_str ( date_time_str, "%Y%m%dT%H%M%SZ" )
386+ . unwrap_or_else ( |_|
387+ // Try taskchampions variant.
388+ chrono:: prelude:: NaiveDateTime :: parse_from_str ( date_time_str, "%Y-%m-%dT%H:%M:%SZ" ) . unwrap ( )
389+ )
390+ . and_utc ( ) ;
391+ Ok ( tera:: to_value ( date_time. to_rfc3339 ( ) ) . unwrap ( ) )
392+ } ,
393+ )
394+ }
395+
364396fn get_date ( ) -> impl tera:: Function {
365397 Box :: new (
366398 move |args : & HashMap < String , tera:: Value > | -> tera:: Result < tera:: Value > {
@@ -422,7 +454,7 @@ fn get_timer() -> impl tera::Function {
422454
423455 let s = if delta. num_hours ( ) > 0 {
424456 format ! (
425- "{:>02}:{:>02}" ,
457+ "{:>02}:{:>02}:00 " ,
426458 delta. num_hours( ) ,
427459 delta. num_minutes( ) - ( delta. num_hours( ) * 60 )
428460 )
@@ -434,7 +466,7 @@ fn get_timer() -> impl tera::Function {
434466 num_seconds % 60
435467 )
436468 } else {
437- format ! ( "{}s " , num_seconds)
469+ format ! ( "00:00:{:>02} " , num_seconds)
438470 } ;
439471 Ok ( tera:: to_value ( s) . unwrap ( ) )
440472 } ,
0 commit comments