util.rs 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. use std::{
  2. env,
  3. fs::{self, File},
  4. io::Write,
  5. process::Command,
  6. };
  7. use chrono::{Datelike, Local, NaiveDate};
  8. use log::error;
  9. use darkfi::{util::time::Timestamp, Result};
  10. /// Parse due date (e.g. "1503" for 15 March) as i64 timestamp.
  11. pub fn due_as_timestamp(due: &str) -> Option<i64> {
  12. if due.len() != 4 || due.parse::<u32>().is_err() {
  13. error!("Due date must be digits of length 4 (e.g. \"1503\" for 15 March)");
  14. return None
  15. }
  16. let (day, month) = (due[..2].parse::<u32>().unwrap(), due[2..].parse::<u32>().unwrap());
  17. if day > 31 || month > 12 {
  18. error!("Invalid or out-of-range date");
  19. return None
  20. }
  21. let mut year = Local::today().year();
  22. // Ensure the due date is in future
  23. if month < Local::today().month() {
  24. year += 1;
  25. }
  26. if month == Local::today().month() && day < Local::today().day() {
  27. year += 1;
  28. }
  29. let dt = NaiveDate::from_ymd(year, month, day).and_hms(12, 0, 0);
  30. Some(dt.timestamp())
  31. }
  32. /// Start up the preferred editor to edit a task's description.
  33. pub fn desc_in_editor() -> Result<Option<String>> {
  34. // Create a temporary file with some comments inside.
  35. let mut file_path = env::temp_dir();
  36. let file_name = format!("tau-{}", Timestamp::current_time().0);
  37. file_path.push(file_name);
  38. let mut file = File::create(&file_path)?;
  39. writeln!(file, "\n# Write your task description here.")?;
  40. writeln!(file, "# Lines starting with \"#\" will be removed")?;
  41. // Try $EDITOR, and if not, fallback to xdg-open.
  42. let editor_argv0 = match env::var("EDITOR") {
  43. Ok(v) => v,
  44. Err(_) => "xdg-open".into(),
  45. };
  46. Command::new(editor_argv0).arg(&file_path).status()?;
  47. // Whatever has been written in the temp file will be read here.
  48. let content = fs::read_to_string(&file_path)?;
  49. fs::remove_file(&file_path)?;
  50. let mut lines = vec![];
  51. for i in content.lines() {
  52. if !i.starts_with('#') {
  53. lines.push(i.to_string())
  54. }
  55. }
  56. Ok(Some(lines.join("\n")))
  57. }