2021-06-30 13:27:42 -05:00
use std ::io ::Write ;
use itertools ::Itertools ;
2021-08-25 14:43:50 -05:00
use chrono ::{ Duration , Local , NaiveTime , Timelike , NaiveDateTime } ;
2021-06-30 13:27:42 -05:00
use crate ::models ::Entry ;
use crate ::error ::Result ;
2021-07-15 00:22:38 -05:00
use crate ::tabulate ::{ Tabulate , Col , Align ::* } ;
2021-08-25 14:43:50 -05:00
use crate ::commands ::Facts ;
2021-06-30 13:27:42 -05:00
2021-07-15 00:22:38 -05:00
pub fn format_duration ( dur : Duration ) -> String {
2021-06-30 13:27:42 -05:00
format! ( " {} : {:02} : {:02} " , dur . num_hours ( ) , dur . num_minutes ( ) % 60 , dur . num_seconds ( ) % 60 )
}
fn format_start ( t : NaiveTime ) -> String {
2021-07-15 11:16:17 -05:00
format! ( " {:02} : {:02} : {:02} " , t . hour ( ) , t . minute ( ) , t . second ( ) )
2021-06-30 13:27:42 -05:00
}
fn format_end ( start : NaiveDateTime , end : NaiveDateTime ) -> String {
let extra_days = ( end - start ) . num_days ( ) ;
let d = if extra_days > 0 { format! ( " + {} d " , extra_days ) } else { " " . into ( ) } ;
format! (
" {:02}:{:02}:{:02}{} " ,
end . hour ( ) ,
end . minute ( ) % 60 ,
end . second ( ) % 60 ,
d
)
}
/// Print in the default text format. Assume entries are sorted by sheet and
/// then by start
2021-08-25 14:43:50 -05:00
pub fn print_formatted < W : Write > ( entries : Vec < Entry > , out : & mut W , facts : & Facts , ids : bool ) -> Result < ( ) > {
2021-06-30 13:27:42 -05:00
let grouped_entries = entries . into_iter ( ) . group_by ( | e | e . sheet . to_string ( ) ) ;
2021-07-16 17:31:30 -05:00
let mut num_sheets = 0 ;
let mut grand_total = Duration ::seconds ( 0 ) ;
for ( i , ( key , group ) ) in grouped_entries . into_iter ( ) . enumerate ( ) {
num_sheets + = 1 ;
if i ! = 0 {
writeln! ( out ) ? ;
}
2021-06-30 13:27:42 -05:00
writeln! ( out , " Timesheet: {} " , key ) ? ;
// A vector of lines to be printed, with all the components
2021-07-15 11:16:17 -05:00
let mut tabs = Tabulate ::with_columns ( vec! [
Col ::min_width ( 3 ) . and_alignment ( Right ) ,
Col ::min_width ( 18 ) . and_alignment ( Left ) ,
Col ::min_width ( 21 ) . and_alignment ( Left ) ,
Col ::min_width ( 8 ) . and_alignment ( Right ) ,
Col ::min_width ( 5 ) . max_width ( 44 ) . and_alignment ( Left ) ,
] ) ;
2021-07-15 00:22:38 -05:00
if ids {
tabs . feed ( vec! [
2021-07-15 11:16:17 -05:00
" ID " . into ( ) , " Day " . into ( ) , " Start End " . into ( ) , " Duration " . into ( ) , " Notes " . into ( ) ,
2021-07-15 00:22:38 -05:00
] ) ;
} else {
tabs . feed ( vec! [
2021-07-15 11:16:17 -05:00
" " . into ( ) , " Day " . into ( ) , " Start End " . into ( ) , " Duration " . into ( ) , " Notes " . into ( ) ,
2021-07-15 00:22:38 -05:00
] ) ;
}
2021-06-30 13:27:42 -05:00
2021-07-16 12:45:27 -05:00
let entries_by_date = group . group_by ( | e | e . start . with_timezone ( & Local ) . date ( ) ) ;
2021-06-30 13:27:42 -05:00
let mut total = Duration ::seconds ( 0 ) ;
for ( date , entries ) in entries_by_date . into_iter ( ) {
let mut daily = Duration ::seconds ( 0 ) ;
for ( i , entry ) in entries . into_iter ( ) . enumerate ( ) {
2021-07-15 11:16:17 -05:00
let startend = format! ( " {} - {} " ,
2021-07-16 12:45:27 -05:00
format_start ( entry . start . with_timezone ( & Local ) . time ( ) ) ,
2021-07-15 11:16:17 -05:00
entry . end . map ( | t | {
format_end (
entry . start . with_timezone ( & Local ) . naive_local ( ) ,
2021-07-16 12:45:27 -05:00
t . with_timezone ( & Local ) . naive_local ( )
2021-07-15 11:16:17 -05:00
)
2021-08-02 19:10:34 -05:00
} ) . unwrap_or_else ( | | " " . into ( ) )
2021-07-15 11:16:17 -05:00
) ;
2021-08-25 14:43:50 -05:00
let duration = entry . end . unwrap_or ( facts . now ) - entry . start ;
2021-06-30 13:27:42 -05:00
daily = daily + duration ;
let duration = format_duration ( duration ) ;
2021-08-02 19:10:34 -05:00
let note = entry . note . unwrap_or_else ( | | " " . into ( ) ) ;
2021-06-30 13:27:42 -05:00
let id = if ids { entry . id . to_string ( ) } else { " " . into ( ) } ;
if i = = 0 {
let date = date . format ( " %a %b %d, %Y " ) . to_string ( ) ;
2021-07-15 11:16:17 -05:00
tabs . feed ( vec! [ id , date , startend , duration , note ] ) ;
2021-06-30 13:27:42 -05:00
} else {
2021-07-15 11:16:17 -05:00
tabs . feed ( vec! [ id , " " . into ( ) , startend , duration , note ] ) ;
2021-06-30 13:27:42 -05:00
}
}
total = total + daily ;
2021-07-15 11:16:17 -05:00
tabs . feed ( vec! [ " " . into ( ) , " " . into ( ) , " " . into ( ) , format_duration ( daily ) , " " . into ( ) ] ) ;
2021-06-30 13:27:42 -05:00
}
2021-07-15 00:22:38 -05:00
tabs . separator ( '-' ) ;
2021-07-15 11:16:17 -05:00
tabs . feed ( vec! [ " " . into ( ) , " Total " . into ( ) , " " . into ( ) , format_duration ( total ) ] ) ;
2021-07-16 17:31:30 -05:00
grand_total = grand_total + total ;
2021-08-25 14:43:50 -05:00
out . write_all ( tabs . print ( facts . env . stdout_is_tty ) . as_bytes ( ) ) ? ;
2021-07-16 17:31:30 -05:00
}
if num_sheets > 1 {
let mut tabs = Tabulate ::with_columns ( vec! [
Col ::min_width ( 3 ) . and_alignment ( Right ) ,
Col ::min_width ( 18 ) . and_alignment ( Left ) ,
Col ::min_width ( 21 ) . and_alignment ( Left ) ,
Col ::min_width ( 8 ) . and_alignment ( Right ) ,
Col ::min_width ( 5 ) . max_width ( 44 ) . and_alignment ( Left ) ,
] ) ;
tabs . separator ( '-' ) ;
tabs . feed ( vec! [ " " . into ( ) , " Grand total " . into ( ) , " " . into ( ) , format_duration ( grand_total ) ] ) ;
2021-06-30 13:27:42 -05:00
2021-08-25 14:43:50 -05:00
out . write_all ( tabs . print ( facts . env . stdout_is_tty ) . as_bytes ( ) ) ? ;
2021-06-30 13:27:42 -05:00
}
Ok ( ( ) )
}
#[ cfg(test) ]
mod tests {
2021-07-15 11:16:17 -05:00
use pretty_assertions ::assert_eq ;
2021-08-25 14:43:50 -05:00
use chrono ::{ Utc , TimeZone } ;
2021-06-30 13:27:42 -05:00
2021-07-15 11:16:17 -05:00
use super ::* ;
2021-12-13 14:20:56 -06:00
const LONG_NOTE : & str = " chatting with bob about upcoming task, district sharing of images, how the user settings currently works etc. Discussing the fingerprinting / cache busting issue with CKEDITOR, suggesting perhaps looking into forking the rubygem and seeing if we can work in our own changes, however hard that might be. " ;
2021-06-30 13:27:42 -05:00
#[ test ]
fn test_text_output ( ) {
2021-08-11 17:54:37 -05:00
std ::env ::set_var ( " TZ " , " CST+6 " ) ;
2021-06-30 13:27:42 -05:00
let mut output = Vec ::new ( ) ;
let entries = vec! [
Entry ::new_sample ( 1 , Utc . ymd ( 2008 , 10 , 3 ) . and_hms ( 12 , 0 , 0 ) , Some ( Utc . ymd ( 2008 , 10 , 3 ) . and_hms ( 14 , 0 , 0 ) ) ) ,
Entry ::new_sample ( 2 , Utc . ymd ( 2008 , 10 , 3 ) . and_hms ( 16 , 0 , 0 ) , Some ( Utc . ymd ( 2008 , 10 , 3 ) . and_hms ( 18 , 0 , 0 ) ) ) ,
Entry ::new_sample ( 3 , Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 16 , 0 , 0 ) , Some ( Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 18 , 0 , 0 ) ) ) ,
Entry ::new_sample ( 4 , Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 18 , 0 , 0 ) , None ) ,
] ;
let now = Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 20 , 0 , 0 ) ;
2021-08-25 14:43:50 -05:00
let facts = Facts ::new ( ) . with_now ( now ) ;
2021-06-30 13:27:42 -05:00
2021-08-25 14:43:50 -05:00
print_formatted ( entries , & mut output , & facts , false ) . unwrap ( ) ;
2021-06-30 13:27:42 -05:00
2022-07-19 05:38:37 -05:00
assert_eq! ( & String ::from_utf8_lossy ( & output ) , " Timesheet: default
2021-06-30 13:27:42 -05:00
Day Start End Duration Notes
2021-08-11 17:54:37 -05:00
Fri Oct 03 , 2008 06 :00 :00 - 08 :00 :00 2 :00 :00 entry 1
10 :00 :00 - 12 :00 :00 2 :00 :00 entry 2
2021-06-30 13:27:42 -05:00
4 :00 :00
2021-08-11 17:54:37 -05:00
Sun Oct 05 , 2008 10 :00 :00 - 12 :00 :00 2 :00 :00 entry 3
12 :00 :00 - 2 :00 :00 entry 4
2021-06-30 13:27:42 -05:00
4 :00 :00
2021-07-15 11:16:17 -05:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2021-06-30 13:27:42 -05:00
Total 8 :00 :00
2022-07-19 05:38:37 -05:00
" );
2021-06-30 13:27:42 -05:00
}
#[ test ]
fn test_text_output_with_millis ( ) {
2021-08-11 17:54:37 -05:00
std ::env ::set_var ( " TZ " , " CST+6 " ) ;
2021-06-30 13:27:42 -05:00
let mut output = Vec ::new ( ) ;
let entries = vec! [
Entry ::new_sample ( 1 , Utc . ymd ( 2008 , 10 , 3 ) . and_hms_milli ( 12 , 0 , 0 , 432 ) , Some ( Utc . ymd ( 2008 , 10 , 3 ) . and_hms_milli ( 14 , 0 , 0 , 312 ) ) ) ,
] ;
let now = Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 20 , 0 , 0 ) ;
2021-08-25 14:43:50 -05:00
let facts = Facts ::new ( ) . with_now ( now ) ;
2021-06-30 13:27:42 -05:00
2021-08-25 14:43:50 -05:00
print_formatted ( entries , & mut output , & facts , false ) . unwrap ( ) ;
2021-06-30 13:27:42 -05:00
2022-07-19 05:38:37 -05:00
assert_eq! ( & String ::from_utf8_lossy ( & output ) , " Timesheet: default
2021-06-30 13:27:42 -05:00
Day Start End Duration Notes
2021-08-11 17:54:37 -05:00
Fri Oct 03 , 2008 06 :00 :00 - 08 :00 :00 1 :59 :59 entry 1
2021-06-30 13:27:42 -05:00
1 :59 :59
2021-07-15 11:16:17 -05:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2021-06-30 13:27:42 -05:00
Total 1 :59 :59
2022-07-19 05:38:37 -05:00
" );
2021-06-30 13:27:42 -05:00
}
#[ test ]
fn test_text_output_long_duration ( ) {
2021-08-11 17:54:37 -05:00
std ::env ::set_var ( " TZ " , " CST+6 " ) ;
2021-06-30 13:27:42 -05:00
let mut output = Vec ::new ( ) ;
let entries = vec! [
Entry ::new_sample ( 1 , Utc . ymd ( 2008 , 10 , 1 ) . and_hms ( 12 , 0 , 0 ) , Some ( Utc . ymd ( 2008 , 10 , 3 ) . and_hms ( 14 , 0 , 0 ) ) ) ,
Entry ::new_sample ( 2 , Utc . ymd ( 2008 , 10 , 3 ) . and_hms ( 12 , 0 , 0 ) , Some ( Utc . ymd ( 2008 , 10 , 3 ) . and_hms ( 14 , 0 , 0 ) ) ) ,
] ;
let now = Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 20 , 0 , 0 ) ;
2021-08-25 14:43:50 -05:00
let facts = Facts ::new ( ) . with_now ( now ) ;
2021-06-30 13:27:42 -05:00
2021-08-25 14:43:50 -05:00
print_formatted ( entries , & mut output , & facts , false ) . unwrap ( ) ;
2021-06-30 13:27:42 -05:00
2022-07-19 05:38:37 -05:00
assert_eq! ( & String ::from_utf8_lossy ( & output ) , " Timesheet: default
2021-06-30 13:27:42 -05:00
Day Start End Duration Notes
2021-08-11 17:54:37 -05:00
Wed Oct 01 , 2008 06 :00 :00 - 08 :00 :00 + 2 d 50 :00 :00 entry 1
2021-06-30 13:27:42 -05:00
50 :00 :00
2021-08-11 17:54:37 -05:00
Fri Oct 03 , 2008 06 :00 :00 - 08 :00 :00 2 :00 :00 entry 2
2021-06-30 13:27:42 -05:00
2 :00 :00
2021-07-15 11:16:17 -05:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2021-06-30 13:27:42 -05:00
Total 52 :00 :00
2022-07-19 05:38:37 -05:00
" );
2021-06-30 13:27:42 -05:00
}
#[ test ]
fn test_text_output_with_ids ( ) {
2021-08-11 17:54:37 -05:00
std ::env ::set_var ( " TZ " , " CST+6 " ) ;
2021-06-30 13:27:42 -05:00
let mut output = Vec ::new ( ) ;
let entries = vec! [
Entry ::new_sample ( 1 , Utc . ymd ( 2008 , 10 , 3 ) . and_hms ( 12 , 0 , 0 ) , Some ( Utc . ymd ( 2008 , 10 , 3 ) . and_hms ( 14 , 0 , 0 ) ) ) ,
Entry ::new_sample ( 2 , Utc . ymd ( 2008 , 10 , 3 ) . and_hms ( 16 , 0 , 0 ) , Some ( Utc . ymd ( 2008 , 10 , 3 ) . and_hms ( 18 , 0 , 0 ) ) ) ,
Entry ::new_sample ( 3 , Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 16 , 0 , 0 ) , Some ( Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 18 , 0 , 0 ) ) ) ,
Entry ::new_sample ( 4 , Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 18 , 0 , 0 ) , None ) ,
] ;
let now = Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 20 , 0 , 0 ) ;
2021-08-25 14:43:50 -05:00
let facts = Facts ::new ( ) . with_now ( now ) ;
2021-06-30 13:27:42 -05:00
2021-08-25 14:43:50 -05:00
print_formatted ( entries , & mut output , & facts , true ) . unwrap ( ) ;
2021-06-30 13:27:42 -05:00
2022-07-19 05:38:37 -05:00
assert_eq! ( & String ::from_utf8_lossy ( & output ) , " Timesheet: default
2021-06-30 13:27:42 -05:00
ID Day Start End Duration Notes
2021-08-11 17:54:37 -05:00
1 Fri Oct 03 , 2008 06 :00 :00 - 08 :00 :00 2 :00 :00 entry 1
2 10 :00 :00 - 12 :00 :00 2 :00 :00 entry 2
2021-06-30 13:27:42 -05:00
4 :00 :00
2021-08-11 17:54:37 -05:00
3 Sun Oct 05 , 2008 10 :00 :00 - 12 :00 :00 2 :00 :00 entry 3
4 12 :00 :00 - 2 :00 :00 entry 4
2021-06-30 13:27:42 -05:00
4 :00 :00
2021-07-15 11:16:17 -05:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2021-06-30 13:27:42 -05:00
Total 8 :00 :00
2022-07-19 05:38:37 -05:00
" );
2021-06-30 13:27:42 -05:00
}
#[ test ]
fn test_text_output_long_note_with_ids ( ) {
2021-08-11 17:54:37 -05:00
std ::env ::set_var ( " TZ " , " CST+6 " ) ;
2021-06-30 13:27:42 -05:00
let mut output = Vec ::new ( ) ;
let entries = vec! [
Entry {
id : 60000 ,
sheet : " default " . into ( ) ,
start : Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 16 , 0 , 0 ) ,
end : Some ( Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 18 , 0 , 0 ) ) ,
2021-06-30 18:51:02 -05:00
note : Some ( LONG_NOTE . into ( ) ) ,
2021-06-30 13:27:42 -05:00
} ,
] ;
let now = Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 20 , 0 , 0 ) ;
2021-08-25 14:43:50 -05:00
let facts = Facts ::new ( ) . with_now ( now ) ;
2021-06-30 13:27:42 -05:00
2021-08-25 14:43:50 -05:00
print_formatted ( entries , & mut output , & facts , true ) . unwrap ( ) ;
2021-06-30 13:27:42 -05:00
2022-07-19 05:38:37 -05:00
assert_eq! ( & String ::from_utf8_lossy ( & output ) , " Timesheet: default
2021-06-30 13:27:42 -05:00
ID Day Start End Duration Notes
2021-08-11 17:54:37 -05:00
60000 Sun Oct 05 , 2008 10 :00 :00 - 12 :00 :00 2 :00 :00 chatting with bob about upcoming task ,
2021-06-30 13:27:42 -05:00
district sharing of images , how the user
settings currently works etc . Discussing the
fingerprinting / cache busting issue with
CKEDITOR , suggesting perhaps looking into
forking the rubygem and seeing if we can
work in our own changes , however hard that
might be .
2 :00 :00
2021-07-15 11:16:17 -05:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2021-06-30 13:27:42 -05:00
Total 2 :00 :00
2022-07-19 05:38:37 -05:00
" );
2021-06-30 13:27:42 -05:00
}
#[ test ]
fn test_text_output_note_with_line_breaks ( ) {
2021-08-11 17:54:37 -05:00
std ::env ::set_var ( " TZ " , " CST+6 " ) ;
2021-06-30 13:27:42 -05:00
let mut output = Vec ::new ( ) ;
let entries = vec! [
Entry {
id : 1 ,
sheet : " default " . into ( ) ,
start : Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 16 , 0 , 0 ) ,
end : Some ( Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 18 , 0 , 0 ) ) ,
2021-06-30 18:51:02 -05:00
note : Some ( " first line \n and a second line " . into ( ) ) ,
2021-06-30 13:27:42 -05:00
} ,
] ;
let now = Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 20 , 0 , 0 ) ;
2021-08-25 14:43:50 -05:00
let facts = Facts ::new ( ) . with_now ( now ) ;
2021-06-30 13:27:42 -05:00
2021-08-25 14:43:50 -05:00
print_formatted ( entries , & mut output , & facts , false ) . unwrap ( ) ;
2021-06-30 13:27:42 -05:00
2022-07-19 05:38:37 -05:00
assert_eq! ( & String ::from_utf8_lossy ( & output ) , " Timesheet: default
2021-06-30 13:27:42 -05:00
Day Start End Duration Notes
2021-08-11 17:54:37 -05:00
Sun Oct 05 , 2008 10 :00 :00 - 12 :00 :00 2 :00 :00 first line
2021-06-30 13:27:42 -05:00
and a second line
2 :00 :00
2021-07-15 11:16:17 -05:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2021-06-30 13:27:42 -05:00
Total 2 :00 :00
2022-07-19 05:38:37 -05:00
" );
2021-07-01 11:45:04 -05:00
}
#[ test ]
fn note_with_accents ( ) {
2021-08-11 17:54:37 -05:00
std ::env ::set_var ( " TZ " , " CST+6 " ) ;
2021-07-01 11:45:04 -05:00
let mut output = Vec ::new ( ) ;
let entries = vec! [
Entry {
id : 1 ,
sheet : " default " . into ( ) ,
start : Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 16 , 0 , 0 ) ,
end : Some ( Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 18 , 0 , 0 ) ) ,
note : Some ( " quiúbole " . into ( ) ) ,
} ,
] ;
let now = Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 20 , 0 , 0 ) ;
2021-08-25 14:43:50 -05:00
let facts = Facts ::new ( ) . with_now ( now ) ;
2021-07-01 11:45:04 -05:00
2021-08-25 14:43:50 -05:00
print_formatted ( entries , & mut output , & facts , false ) . unwrap ( ) ;
2021-07-01 11:45:04 -05:00
2022-07-19 05:38:37 -05:00
assert_eq! ( & String ::from_utf8_lossy ( & output ) , " Timesheet: default
2021-07-01 11:45:04 -05:00
Day Start End Duration Notes
2021-08-11 17:54:37 -05:00
Sun Oct 05 , 2008 10 :00 :00 - 12 :00 :00 2 :00 :00 quiúbole
2021-07-01 11:45:04 -05:00
2 :00 :00
2021-07-15 11:16:17 -05:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2021-07-01 11:45:04 -05:00
Total 2 :00 :00
2022-07-19 05:38:37 -05:00
" );
2021-07-16 17:31:30 -05:00
}
#[ test ]
fn displays_grand_total_when_multiple_sheets ( ) {
2021-08-11 17:54:37 -05:00
std ::env ::set_var ( " TZ " , " CST+6 " ) ;
2021-07-16 17:31:30 -05:00
let mut output = Vec ::new ( ) ;
let entries = vec! [
Entry {
id : 1 ,
sheet : " sheet1 " . into ( ) ,
start : Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 16 , 0 , 0 ) ,
end : Some ( Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 18 , 0 , 0 ) ) ,
note : Some ( " quiúbole " . into ( ) ) ,
} ,
Entry {
id : 2 ,
sheet : " sheet2 " . into ( ) ,
start : Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 16 , 0 , 0 ) ,
end : Some ( Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 18 , 0 , 0 ) ) ,
note : Some ( " quiúbole " . into ( ) ) ,
} ,
] ;
let now = Utc . ymd ( 2008 , 10 , 5 ) . and_hms ( 20 , 0 , 0 ) ;
2021-08-25 14:43:50 -05:00
let facts = Facts ::new ( ) . with_now ( now ) ;
2021-07-16 17:31:30 -05:00
2021-08-25 14:43:50 -05:00
print_formatted ( entries , & mut output , & facts , false ) . unwrap ( ) ;
2021-07-16 17:31:30 -05:00
2022-07-19 05:38:37 -05:00
assert_eq! ( & String ::from_utf8_lossy ( & output ) , " Timesheet: sheet1
2021-07-16 17:31:30 -05:00
Day Start End Duration Notes
2021-08-11 17:54:37 -05:00
Sun Oct 05 , 2008 10 :00 :00 - 12 :00 :00 2 :00 :00 quiúbole
2021-07-16 17:31:30 -05:00
2 :00 :00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Total 2 :00 :00
Timesheet : sheet2
Day Start End Duration Notes
2021-08-11 17:54:37 -05:00
Sun Oct 05 , 2008 10 :00 :00 - 12 :00 :00 2 :00 :00 quiúbole
2021-07-16 17:31:30 -05:00
2 :00 :00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Total 2 :00 :00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Grand total 4 :00 :00
2022-07-19 05:38:37 -05:00
" );
2021-06-30 13:27:42 -05:00
}
}