Merge pull request #941 from matthiasbeyer/libimagentrydate/init
libimagentrydate/init
This commit is contained in:
commit
16a12af873
14 changed files with 1087 additions and 0 deletions
|
@ -17,6 +17,7 @@ members = [
|
||||||
"libimagbookmark",
|
"libimagbookmark",
|
||||||
"libimagcounter",
|
"libimagcounter",
|
||||||
"libimagdiary",
|
"libimagdiary",
|
||||||
|
"libimagentrydatetime",
|
||||||
"libimagentryedit",
|
"libimagentryedit",
|
||||||
"libimagentryfilter",
|
"libimagentryfilter",
|
||||||
"libimagentrylink",
|
"libimagentrylink",
|
||||||
|
|
33
libimagentrydatetime/Cargo.toml
Normal file
33
libimagentrydatetime/Cargo.toml
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
[package]
|
||||||
|
name = "libimagentrydatetime"
|
||||||
|
version = "0.3.0"
|
||||||
|
authors = ["Matthias Beyer <mail@beyermatthias.de>"]
|
||||||
|
|
||||||
|
description = "Library for the imag core distribution"
|
||||||
|
|
||||||
|
keywords = ["imag", "PIM", "personal", "information", "management"]
|
||||||
|
readme = "../README.md"
|
||||||
|
license = "LGPL-2.1"
|
||||||
|
|
||||||
|
documentation = "https://matthiasbeyer.github.io/imag/imag_documentation/index.html"
|
||||||
|
repository = "https://github.com/matthiasbeyer/imag"
|
||||||
|
homepage = "http://imag-pim.org"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
chrono = "0.3"
|
||||||
|
toml-query = "0.2"
|
||||||
|
lazy_static = "0.2"
|
||||||
|
toml = "0.4"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
is-match = "0.1"
|
||||||
|
|
||||||
|
[dependencies.libimagerror]
|
||||||
|
path = "../libimagerror"
|
||||||
|
|
||||||
|
[dependencies.libimagstore]
|
||||||
|
path = "../libimagstore"
|
||||||
|
|
||||||
|
[dependencies.libimagutil]
|
||||||
|
path = "../libimagutil"
|
||||||
|
|
112
libimagentrydatetime/src/datepath/accuracy.rs
Normal file
112
libimagentrydatetime/src/datepath/accuracy.rs
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
//
|
||||||
|
// imag - the personal information management suite for the commandline
|
||||||
|
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; version
|
||||||
|
// 2.1 of the License.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
//
|
||||||
|
|
||||||
|
/// The accuracy with which the compiler should compile the time specification
|
||||||
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||||
|
pub enum Accuracy {
|
||||||
|
Year,
|
||||||
|
Month,
|
||||||
|
Day,
|
||||||
|
Hour,
|
||||||
|
Minute,
|
||||||
|
Second
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Accuracy {
|
||||||
|
|
||||||
|
/// Check whether the current setting includes a year.
|
||||||
|
pub fn has_year_accuracy(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Accuracy::Year => true,
|
||||||
|
Accuracy::Month => true,
|
||||||
|
Accuracy::Day => true,
|
||||||
|
Accuracy::Hour => true,
|
||||||
|
Accuracy::Minute => true,
|
||||||
|
Accuracy::Second => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check whether the current setting includes a month.
|
||||||
|
pub fn has_month_accuracy(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Accuracy::Year => false,
|
||||||
|
Accuracy::Month => true,
|
||||||
|
Accuracy::Day => true,
|
||||||
|
Accuracy::Hour => true,
|
||||||
|
Accuracy::Minute => true,
|
||||||
|
Accuracy::Second => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check whether the current setting includes a day.
|
||||||
|
pub fn has_day_accuracy(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Accuracy::Year => false,
|
||||||
|
Accuracy::Month => false,
|
||||||
|
Accuracy::Day => true,
|
||||||
|
Accuracy::Hour => true,
|
||||||
|
Accuracy::Minute => true,
|
||||||
|
Accuracy::Second => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check whether the current setting includes a hour.
|
||||||
|
pub fn has_hour_accuracy(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Accuracy::Year => false,
|
||||||
|
Accuracy::Month => false,
|
||||||
|
Accuracy::Day => false,
|
||||||
|
Accuracy::Hour => true,
|
||||||
|
Accuracy::Minute => true,
|
||||||
|
Accuracy::Second => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check whether the current setting includes a minute.
|
||||||
|
pub fn has_minute_accuracy(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Accuracy::Year => false,
|
||||||
|
Accuracy::Month => false,
|
||||||
|
Accuracy::Day => false,
|
||||||
|
Accuracy::Hour => false,
|
||||||
|
Accuracy::Minute => true,
|
||||||
|
Accuracy::Second => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check whether the current setting includes a second.
|
||||||
|
pub fn has_second_accuracy(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Accuracy::Year => false,
|
||||||
|
Accuracy::Month => false,
|
||||||
|
Accuracy::Day => false,
|
||||||
|
Accuracy::Hour => false,
|
||||||
|
Accuracy::Minute => false,
|
||||||
|
Accuracy::Second => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Accuracy {
|
||||||
|
fn default() -> Accuracy {
|
||||||
|
Accuracy::Second
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
196
libimagentrydatetime/src/datepath/compiler.rs
Normal file
196
libimagentrydatetime/src/datepath/compiler.rs
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
//
|
||||||
|
// imag - the personal information management suite for the commandline
|
||||||
|
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; version
|
||||||
|
// 2.1 of the License.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
//
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use chrono::naive::datetime::NaiveDateTime;
|
||||||
|
use chrono::Datelike;
|
||||||
|
use chrono::Timelike;
|
||||||
|
|
||||||
|
use libimagstore::storeid::StoreId;
|
||||||
|
|
||||||
|
use datepath::accuracy::Accuracy;
|
||||||
|
use datepath::format::Format;
|
||||||
|
use datepath::result::Result;
|
||||||
|
use datepath::error::DatePathCompilerErrorKind as DPCEK;
|
||||||
|
use datepath::error::MapErrInto;
|
||||||
|
|
||||||
|
pub struct DatePathCompiler {
|
||||||
|
accuracy : Accuracy,
|
||||||
|
format : Format,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DatePathCompiler {
|
||||||
|
|
||||||
|
pub fn new(accuracy: Accuracy, format: Format) -> DatePathCompiler {
|
||||||
|
DatePathCompiler {
|
||||||
|
accuracy : accuracy,
|
||||||
|
format : format,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile a NaiveDateTime object into a StoreId object.
|
||||||
|
///
|
||||||
|
/// # More information
|
||||||
|
///
|
||||||
|
/// See the documentations of the `Format` and the `Accuracy` types as well.
|
||||||
|
///
|
||||||
|
/// # Warnings
|
||||||
|
///
|
||||||
|
/// This does _not_ guarantee that the StoreId can be created, is not yet in the store or
|
||||||
|
/// anything else. Overall, this is just a `spec->path` compiler which is really stupid.
|
||||||
|
///
|
||||||
|
/// # Return value
|
||||||
|
///
|
||||||
|
/// The `StoreId` object on success.
|
||||||
|
///
|
||||||
|
pub fn compile(&self, module_name: &str, datetime: &NaiveDateTime) -> Result<StoreId> {
|
||||||
|
let mut s = format!("{}/", module_name);
|
||||||
|
|
||||||
|
if self.accuracy.has_year_accuracy() /* always true */ {
|
||||||
|
s.push_str(&format!("{:04}", datetime.year()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.accuracy.has_month_accuracy() {
|
||||||
|
match self.format {
|
||||||
|
Format::ElementIsFolder
|
||||||
|
| Format::DaysAreFolder
|
||||||
|
| Format::MonthIsFolder
|
||||||
|
| Format::YearIsFolder
|
||||||
|
=> s.push_str(&format!("/{:02}", datetime.month())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.accuracy.has_day_accuracy() {
|
||||||
|
match self.format {
|
||||||
|
Format::ElementIsFolder
|
||||||
|
| Format::DaysAreFolder
|
||||||
|
| Format::MonthIsFolder
|
||||||
|
=> s.push_str(&format!("/{:02}", datetime.day())),
|
||||||
|
Format::YearIsFolder
|
||||||
|
=> s.push_str(&format!("-{:02}", datetime.day())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.accuracy.has_hour_accuracy() {
|
||||||
|
match self.format {
|
||||||
|
Format::ElementIsFolder
|
||||||
|
| Format::DaysAreFolder
|
||||||
|
=> s.push_str(&format!("/{:02}", datetime.hour())),
|
||||||
|
Format::YearIsFolder
|
||||||
|
| Format::MonthIsFolder
|
||||||
|
=> s.push_str(&format!("-{:02}", datetime.hour())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.accuracy.has_minute_accuracy() {
|
||||||
|
match self.format {
|
||||||
|
Format::ElementIsFolder
|
||||||
|
=> s.push_str(&format!("/{:02}", datetime.minute())),
|
||||||
|
Format::YearIsFolder
|
||||||
|
| Format::MonthIsFolder
|
||||||
|
| Format::DaysAreFolder
|
||||||
|
=> s.push_str(&format!("-{:02}", datetime.minute())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.accuracy.has_second_accuracy() {
|
||||||
|
match self.format {
|
||||||
|
Format::ElementIsFolder
|
||||||
|
=> s.push_str(&format!("/{:02}", datetime.second())),
|
||||||
|
Format::YearIsFolder
|
||||||
|
| Format::MonthIsFolder
|
||||||
|
| Format::DaysAreFolder
|
||||||
|
=> s.push_str(&format!("-{:02}", datetime.second())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StoreId::new_baseless(PathBuf::from(s))
|
||||||
|
.map_err_into(DPCEK::StoreIdBuildFailed)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use datepath::accuracy::Accuracy;
|
||||||
|
use datepath::format::Format;
|
||||||
|
|
||||||
|
use chrono::naive::date::NaiveDate;
|
||||||
|
use chrono::naive::datetime::NaiveDateTime;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_compiler_compile_simple() {
|
||||||
|
let dt = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
|
||||||
|
let compiler = DatePathCompiler::new(Accuracy::default(), Format::default());
|
||||||
|
let res = compiler.compile("testmodule", &dt);
|
||||||
|
|
||||||
|
assert!(res.is_ok());
|
||||||
|
let res = res.unwrap();
|
||||||
|
|
||||||
|
let s = res.to_str();
|
||||||
|
|
||||||
|
assert!(s.is_ok());
|
||||||
|
let s = s.unwrap();
|
||||||
|
|
||||||
|
assert_eq!("testmodule/2000/01/01/00/00/00", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_accuracy(acc: Accuracy, dt: NaiveDateTime, modname: &str, matchstr: &str) {
|
||||||
|
let compiler = DatePathCompiler::new(acc, Format::default());
|
||||||
|
let res = compiler.compile(modname, &dt);
|
||||||
|
|
||||||
|
assert!(res.is_ok());
|
||||||
|
let res = res.unwrap();
|
||||||
|
|
||||||
|
let s = res.to_str();
|
||||||
|
|
||||||
|
assert!(s.is_ok());
|
||||||
|
let s = s.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(matchstr, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_compiler_compile_year_accuracy() {
|
||||||
|
let dt = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
|
||||||
|
test_accuracy(Accuracy::Year, dt, "module", "module/2000");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_compiler_compile_month_accuracy() {
|
||||||
|
let dt = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
|
||||||
|
test_accuracy(Accuracy::Month, dt, "module", "module/2000/01");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_compiler_compile_day_accuracy() {
|
||||||
|
let dt = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
|
||||||
|
test_accuracy(Accuracy::Day, dt, "module", "module/2000/01/01");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_compiler_compile_year_paddning() {
|
||||||
|
let dt = NaiveDate::from_ymd(1, 1, 1).and_hms(0, 0, 0);
|
||||||
|
test_accuracy(Accuracy::Day, dt, "module", "module/0001/01/01");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
30
libimagentrydatetime/src/datepath/error.rs
Normal file
30
libimagentrydatetime/src/datepath/error.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
// imag - the personal information management suite for the commandline
|
||||||
|
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; version
|
||||||
|
// 2.1 of the License.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Error module for the DatePathCompiler type
|
||||||
|
generate_error_module! {
|
||||||
|
generate_error_types!(DatePathCompilerError, DatePathCompilerErrorKind,
|
||||||
|
UnknownDatePathCompilerError => "Unknown DatePathCompiler error",
|
||||||
|
StoreIdBuildFailed => "Failed building StoreId object"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
pub use self::error::DatePathCompilerError;
|
||||||
|
pub use self::error::DatePathCompilerErrorKind;
|
||||||
|
pub use self::error::MapErrInto;
|
||||||
|
|
92
libimagentrydatetime/src/datepath/format.rs
Normal file
92
libimagentrydatetime/src/datepath/format.rs
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
//
|
||||||
|
// imag - the personal information management suite for the commandline
|
||||||
|
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; version
|
||||||
|
// 2.1 of the License.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
//
|
||||||
|
|
||||||
|
/// The format which should be used to compile the datetime spec into a StoreId object.
|
||||||
|
///
|
||||||
|
/// # Warning
|
||||||
|
///
|
||||||
|
/// These settings depend on the Accuracy settings of the compiler as well.
|
||||||
|
///
|
||||||
|
/// If the compiler settings only specify an accuracy of `Accuracy::Month`, a setting of
|
||||||
|
/// `Format::ElementIsFolder` will result in the `month` beeing the file name.
|
||||||
|
///
|
||||||
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||||
|
pub enum Format {
|
||||||
|
/// Each element of the Path is one folder level.
|
||||||
|
///
|
||||||
|
/// This is the default.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// The date "1st May of 2017, 14:15:16" will be compiled to `2017/05/01/14/15/16`.
|
||||||
|
///
|
||||||
|
/// The second is the filename, then.
|
||||||
|
///
|
||||||
|
/// # Usecase
|
||||||
|
///
|
||||||
|
/// When expecting a lot of entries, this makes sure that the tree is fast-traversible and has
|
||||||
|
/// few files per folder (maximum 60).
|
||||||
|
///
|
||||||
|
ElementIsFolder,
|
||||||
|
|
||||||
|
/// Each element from Year to Day is folder, below is filename.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// The date "1st May of 2017, 14:15:16" will be compiled to `2017/05/01/14-15-16`.
|
||||||
|
///
|
||||||
|
/// # Usecase
|
||||||
|
///
|
||||||
|
/// When expecting few entries per day.
|
||||||
|
///
|
||||||
|
DaysAreFolder,
|
||||||
|
|
||||||
|
/// Each element from Year to Month is folder, below is filename.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// The date "1st May of 2017, 14:15:16" will be compiled to `2017/05/01T14-15-16`.
|
||||||
|
///
|
||||||
|
/// # Usecase
|
||||||
|
///
|
||||||
|
/// When expecting few entries per month.
|
||||||
|
///
|
||||||
|
MonthIsFolder,
|
||||||
|
|
||||||
|
/// Each element from Year to Month is folder, below is filename.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// The date "1st May of 2017, 14:15:16" will be compiled to `2017/05-01T14-15-16`.
|
||||||
|
///
|
||||||
|
/// # Usecase
|
||||||
|
///
|
||||||
|
/// When expecting few entries per year.
|
||||||
|
/// Might be never used.
|
||||||
|
///
|
||||||
|
YearIsFolder,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Format {
|
||||||
|
fn default() -> Format {
|
||||||
|
Format::ElementIsFolder
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
26
libimagentrydatetime/src/datepath/mod.rs
Normal file
26
libimagentrydatetime/src/datepath/mod.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
//
|
||||||
|
// imag - the personal information management suite for the commandline
|
||||||
|
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; version
|
||||||
|
// 2.1 of the License.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
//
|
||||||
|
|
||||||
|
pub mod accuracy;
|
||||||
|
pub mod compiler;
|
||||||
|
pub mod error;
|
||||||
|
pub mod format;
|
||||||
|
pub mod result;
|
||||||
|
pub mod to_store_id;
|
||||||
|
|
25
libimagentrydatetime/src/datepath/result.rs
Normal file
25
libimagentrydatetime/src/datepath/result.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
//
|
||||||
|
// imag - the personal information management suite for the commandline
|
||||||
|
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; version
|
||||||
|
// 2.1 of the License.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Result type for this module.
|
||||||
|
use super::error::DatePathCompilerError as DPCE;
|
||||||
|
use std::result::Result as RResult;
|
||||||
|
|
||||||
|
pub type Result<T> = RResult<T, DPCE>;
|
||||||
|
|
39
libimagentrydatetime/src/datepath/to_store_id.rs
Normal file
39
libimagentrydatetime/src/datepath/to_store_id.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// imag - the personal information management suite for the commandline
|
||||||
|
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; version
|
||||||
|
// 2.1 of the License.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
//
|
||||||
|
|
||||||
|
use chrono::naive::datetime::NaiveDateTime;
|
||||||
|
|
||||||
|
use libimagstore::storeid::StoreId;
|
||||||
|
use datepath::result::Result;
|
||||||
|
use datepath::compiler::DatePathCompiler;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Extension Trait for NaiveDateTime
|
||||||
|
//
|
||||||
|
|
||||||
|
pub trait ToStoreId {
|
||||||
|
fn to_store_id(&self, modname: &str, compiler: &DatePathCompiler) -> Result<StoreId>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToStoreId for NaiveDateTime {
|
||||||
|
fn to_store_id(&self, modname: &str, compiler: &DatePathCompiler) -> Result<StoreId> {
|
||||||
|
compiler.compile(modname, self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
321
libimagentrydatetime/src/datetime.rs
Normal file
321
libimagentrydatetime/src/datetime.rs
Normal file
|
@ -0,0 +1,321 @@
|
||||||
|
//
|
||||||
|
// imag - the personal information management suite for the commandline
|
||||||
|
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; version
|
||||||
|
// 2.1 of the License.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
//
|
||||||
|
|
||||||
|
use chrono::naive::datetime::NaiveDateTime;
|
||||||
|
use toml_query::delete::TomlValueDeleteExt;
|
||||||
|
use toml_query::insert::TomlValueInsertExt;
|
||||||
|
use toml_query::read::TomlValueReadExt;
|
||||||
|
use toml::Value;
|
||||||
|
|
||||||
|
use libimagstore::store::Entry;
|
||||||
|
use libimagerror::into::IntoError;
|
||||||
|
|
||||||
|
use error::DateErrorKind as DEK;
|
||||||
|
use error::*;
|
||||||
|
use result::Result;
|
||||||
|
use range::DateTimeRange;
|
||||||
|
|
||||||
|
pub trait EntryDate {
|
||||||
|
|
||||||
|
fn delete_date(&mut self) -> Result<()>;
|
||||||
|
fn read_date(&self) -> Result<NaiveDateTime>;
|
||||||
|
fn set_date(&mut self, d: NaiveDateTime) -> Result<Option<Result<NaiveDateTime>>>;
|
||||||
|
|
||||||
|
fn delete_date_range(&mut self) -> Result<()>;
|
||||||
|
fn read_date_range(&self) -> Result<DateTimeRange>;
|
||||||
|
fn set_date_range(&mut self, start: NaiveDateTime, end: NaiveDateTime) -> Result<Option<Result<DateTimeRange>>>;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref DATE_HEADER_LOCATION : &'static str = "date.value";
|
||||||
|
static ref DATE_RANGE_START_HEADER_LOCATION : &'static str = "date.range.start";
|
||||||
|
static ref DATE_RANGE_END_HEADER_LOCATION : &'static str = "date.range.end";
|
||||||
|
static ref DATE_FMT : &'static str = "%Y-%m-%dT%H:%M:%S";
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EntryDate for Entry {
|
||||||
|
|
||||||
|
fn delete_date(&mut self) -> Result<()> {
|
||||||
|
self.get_header_mut()
|
||||||
|
.delete(&DATE_HEADER_LOCATION)
|
||||||
|
.map(|_| ())
|
||||||
|
.map_err_into(DEK::DeleteDateError)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_date(&self) -> Result<NaiveDateTime> {
|
||||||
|
self.get_header()
|
||||||
|
.read(&DATE_HEADER_LOCATION)
|
||||||
|
.map_err_into(DEK::ReadDateError)
|
||||||
|
.and_then(|v| {
|
||||||
|
match v {
|
||||||
|
&Value::String(ref s) => s.parse::<NaiveDateTime>()
|
||||||
|
.map_err_into(DEK::DateTimeParsingError),
|
||||||
|
_ => Err(DEK::DateHeaderFieldTypeError.into_error()),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set a Date for this entry
|
||||||
|
///
|
||||||
|
/// # Return value
|
||||||
|
///
|
||||||
|
/// This function returns funny things, I know. But I find it more attractive to be explicit
|
||||||
|
/// what failed when here, instead of beeing nice to the user here.
|
||||||
|
///
|
||||||
|
/// So here's a list how things are returned:
|
||||||
|
///
|
||||||
|
/// - Err(_) if the inserting failed
|
||||||
|
/// - Ok(None) if the inserting succeeded and _did not replace an existing value_.
|
||||||
|
/// - Ok(Some(Ok(_))) if the inserting succeeded, but replaced an existing value which then got
|
||||||
|
/// parsed into a NaiveDateTime object
|
||||||
|
/// - Ok(Some(Err(_))) if the inserting succeeded, but replaced an existing value which then
|
||||||
|
/// got parsed into a NaiveDateTime object, where the parsing failed for some reason.
|
||||||
|
///
|
||||||
|
fn set_date(&mut self, d: NaiveDateTime) -> Result<Option<Result<NaiveDateTime>>> {
|
||||||
|
let date = d.format(&DATE_FMT).to_string();
|
||||||
|
|
||||||
|
self.get_header_mut()
|
||||||
|
.insert(&DATE_HEADER_LOCATION, Value::String(date))
|
||||||
|
.map(|opt| opt.map(|stri| {
|
||||||
|
match stri {
|
||||||
|
Value::String(ref s) => s.parse::<NaiveDateTime>()
|
||||||
|
.map_err_into(DEK::DateTimeParsingError),
|
||||||
|
_ => Err(DEK::DateHeaderFieldTypeError.into_error()),
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.map_err_into(DEK::SetDateError)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Deletes the date range
|
||||||
|
///
|
||||||
|
/// # Warning
|
||||||
|
///
|
||||||
|
/// First deletes the start, then the end. If the first operation fails, this might leave the
|
||||||
|
/// header in an inconsistent state.
|
||||||
|
///
|
||||||
|
fn delete_date_range(&mut self) -> Result<()> {
|
||||||
|
let _ = try!(self
|
||||||
|
.get_header_mut()
|
||||||
|
.delete(&DATE_RANGE_START_HEADER_LOCATION)
|
||||||
|
.map(|_| ())
|
||||||
|
.map_err_into(DEK::DeleteDateTimeRangeError));
|
||||||
|
|
||||||
|
self.get_header_mut()
|
||||||
|
.delete(&DATE_RANGE_END_HEADER_LOCATION)
|
||||||
|
.map(|_| ())
|
||||||
|
.map_err_into(DEK::DeleteDateTimeRangeError)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_date_range(&self) -> Result<DateTimeRange> {
|
||||||
|
let start = try!(self
|
||||||
|
.get_header()
|
||||||
|
.read(&DATE_RANGE_START_HEADER_LOCATION)
|
||||||
|
.map_err_into(DEK::ReadDateTimeRangeError)
|
||||||
|
.and_then(|v| {
|
||||||
|
match v {
|
||||||
|
&Value::String(ref s) => s.parse::<NaiveDateTime>()
|
||||||
|
.map_err_into(DEK::DateTimeParsingError),
|
||||||
|
_ => Err(DEK::DateHeaderFieldTypeError.into_error()),
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
let end = try!(self
|
||||||
|
.get_header()
|
||||||
|
.read(&DATE_RANGE_START_HEADER_LOCATION)
|
||||||
|
.map_err_into(DEK::ReadDateTimeRangeError)
|
||||||
|
.and_then(|v| {
|
||||||
|
match v {
|
||||||
|
&Value::String(ref s) => s.parse::<NaiveDateTime>()
|
||||||
|
.map_err_into(DEK::DateTimeParsingError),
|
||||||
|
_ => Err(DEK::DateHeaderFieldTypeError.into_error()),
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
DateTimeRange::new(start, end)
|
||||||
|
.map_err_into(DEK::DateTimeRangeError)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the date range
|
||||||
|
///
|
||||||
|
/// # Warning
|
||||||
|
///
|
||||||
|
/// This first sets the start, then the end. If the first operation fails, this might leave the
|
||||||
|
/// header in an inconsistent state.
|
||||||
|
///
|
||||||
|
fn set_date_range(&mut self, start: NaiveDateTime, end: NaiveDateTime)
|
||||||
|
-> Result<Option<Result<DateTimeRange>>>
|
||||||
|
{
|
||||||
|
let start = start.format(&DATE_FMT).to_string();
|
||||||
|
let end = end.format(&DATE_FMT).to_string();
|
||||||
|
|
||||||
|
let opt_old_start = try!(self
|
||||||
|
.get_header_mut()
|
||||||
|
.insert(&DATE_RANGE_START_HEADER_LOCATION, Value::String(start))
|
||||||
|
.map(|opt| opt.map(|stri| {
|
||||||
|
match stri {
|
||||||
|
Value::String(ref s) => s.parse::<NaiveDateTime>()
|
||||||
|
.map_err_into(DEK::DateTimeParsingError),
|
||||||
|
_ => Err(DEK::DateHeaderFieldTypeError.into_error()),
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.map_err_into(DEK::SetDateTimeRangeError));
|
||||||
|
|
||||||
|
let opt_old_end = try!(self
|
||||||
|
.get_header_mut()
|
||||||
|
.insert(&DATE_RANGE_END_HEADER_LOCATION, Value::String(end))
|
||||||
|
.map(|opt| opt.map(|stri| {
|
||||||
|
match stri {
|
||||||
|
Value::String(ref s) => s.parse::<NaiveDateTime>()
|
||||||
|
.map_err_into(DEK::DateTimeParsingError),
|
||||||
|
_ => Err(DEK::DateHeaderFieldTypeError.into_error()),
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.map_err_into(DEK::SetDateTimeRangeError));
|
||||||
|
|
||||||
|
match (opt_old_start, opt_old_end) {
|
||||||
|
(Some(Ok(old_start)), Some(Ok(old_end))) => {
|
||||||
|
let dr = DateTimeRange::new(old_start, old_end)
|
||||||
|
.map_err_into(DEK::DateTimeRangeError);
|
||||||
|
|
||||||
|
Ok(Some(dr))
|
||||||
|
},
|
||||||
|
|
||||||
|
(Some(Err(e)), _) => Err(e),
|
||||||
|
(_, Some(Err(e))) => Err(e),
|
||||||
|
_ => {
|
||||||
|
Ok(None)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use libimagstore::store::Store;
|
||||||
|
|
||||||
|
use chrono::naive::datetime::NaiveDateTime;
|
||||||
|
use chrono::naive::date::NaiveDate;
|
||||||
|
use chrono::naive::time::NaiveTime;
|
||||||
|
|
||||||
|
pub fn get_store() -> Store {
|
||||||
|
Store::new(PathBuf::from("/"), None).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_set_date() {
|
||||||
|
let store = get_store();
|
||||||
|
|
||||||
|
let date = {
|
||||||
|
let date = NaiveDate::from_ymd(2000, 01, 02);
|
||||||
|
let time = NaiveTime::from_hms(03, 04, 05);
|
||||||
|
|
||||||
|
NaiveDateTime::new(date, time)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut entry = store.create(PathBuf::from("test")).unwrap();
|
||||||
|
let res = entry.set_date(date);
|
||||||
|
|
||||||
|
assert!(res.is_ok(), format!("Error: {:?}", res));
|
||||||
|
let res = res.unwrap();
|
||||||
|
|
||||||
|
assert!(res.is_none()); // There shouldn't be an existing value
|
||||||
|
|
||||||
|
// Check whether the header is set correctly
|
||||||
|
|
||||||
|
let hdr_field = entry.get_header().read(&DATE_HEADER_LOCATION);
|
||||||
|
|
||||||
|
assert!(hdr_field.is_ok());
|
||||||
|
let hdr_field = hdr_field.unwrap();
|
||||||
|
|
||||||
|
match *hdr_field {
|
||||||
|
Value::String(ref s) => assert_eq!("2000-01-02T03:04:05", s),
|
||||||
|
_ => assert!(false, "Wrong header type"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_read_date() {
|
||||||
|
use chrono::Datelike;
|
||||||
|
use chrono::Timelike;
|
||||||
|
|
||||||
|
let store = get_store();
|
||||||
|
|
||||||
|
let date = {
|
||||||
|
let date = NaiveDate::from_ymd(2000, 01, 02);
|
||||||
|
let time = NaiveTime::from_hms(03, 04, 05);
|
||||||
|
|
||||||
|
NaiveDateTime::new(date, time)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut entry = store.create(PathBuf::from("test")).unwrap();
|
||||||
|
let res = entry.set_date(date);
|
||||||
|
|
||||||
|
assert!(res.is_ok(), format!("Expected Ok(_), got: {:?}", res));
|
||||||
|
let res = res.unwrap();
|
||||||
|
|
||||||
|
assert!(res.is_none()); // There shouldn't be an existing value
|
||||||
|
|
||||||
|
// same as the test above ...
|
||||||
|
|
||||||
|
let d = entry.read_date();
|
||||||
|
|
||||||
|
assert!(d.is_ok(), format!("Expected Ok(_), got: {:?}", d));
|
||||||
|
let d = d.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(d.date().year() , 2000);
|
||||||
|
assert_eq!(d.date().month() , 01);
|
||||||
|
assert_eq!(d.date().day() , 02);
|
||||||
|
assert_eq!(d.time().hour() , 03);
|
||||||
|
assert_eq!(d.time().minute() , 04);
|
||||||
|
assert_eq!(d.time().second() , 05);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_date() {
|
||||||
|
let store = get_store();
|
||||||
|
|
||||||
|
let date = {
|
||||||
|
let date = NaiveDate::from_ymd(2000, 01, 02);
|
||||||
|
let time = NaiveTime::from_hms(03, 04, 05);
|
||||||
|
|
||||||
|
NaiveDateTime::new(date, time)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut entry = store.create(PathBuf::from("test")).unwrap();
|
||||||
|
let res = entry.set_date(date);
|
||||||
|
|
||||||
|
assert!(res.is_ok(), format!("Expected Ok(_), got: {:?}", res));
|
||||||
|
let res = res.unwrap();
|
||||||
|
assert!(res.is_none()); // There shouldn't be an existing value
|
||||||
|
|
||||||
|
assert!(entry.delete_date().is_ok());
|
||||||
|
|
||||||
|
let hdr_field = entry.get_header().read(&DATE_HEADER_LOCATION);
|
||||||
|
|
||||||
|
assert!(hdr_field.is_err(), format!("Expected Err(_), got: {:?}", hdr_field));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
39
libimagentrydatetime/src/error.rs
Normal file
39
libimagentrydatetime/src/error.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// imag - the personal information management suite for the commandline
|
||||||
|
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; version
|
||||||
|
// 2.1 of the License.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
//
|
||||||
|
|
||||||
|
generate_error_module!(
|
||||||
|
generate_error_types!(DateError, DateErrorKind,
|
||||||
|
DeleteDateError => "Error deleting date",
|
||||||
|
ReadDateError => "Error reading date",
|
||||||
|
SetDateError => "Error setting date",
|
||||||
|
DeleteDateTimeRangeError => "Error deleting date-time range",
|
||||||
|
ReadDateTimeRangeError => "Error reading date-time range",
|
||||||
|
SetDateTimeRangeError => "Error setting date-time range",
|
||||||
|
|
||||||
|
DateTimeRangeError => "DateTime Range error",
|
||||||
|
|
||||||
|
DateHeaderFieldTypeError => "Expected the header field in the entry to have type 'String', but have other type",
|
||||||
|
DateTimeParsingError => "Error parsing DateTime"
|
||||||
|
);
|
||||||
|
);
|
||||||
|
|
||||||
|
pub use self::error::DateError;
|
||||||
|
pub use self::error::DateErrorKind;
|
||||||
|
pub use self::error::MapErrInto;
|
||||||
|
|
37
libimagentrydatetime/src/lib.rs
Normal file
37
libimagentrydatetime/src/lib.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
//
|
||||||
|
// imag - the personal information management suite for the commandline
|
||||||
|
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; version
|
||||||
|
// 2.1 of the License.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
//
|
||||||
|
|
||||||
|
#[macro_use] extern crate lazy_static;
|
||||||
|
extern crate chrono;
|
||||||
|
extern crate toml_query;
|
||||||
|
extern crate toml;
|
||||||
|
|
||||||
|
#[macro_use] extern crate libimagerror;
|
||||||
|
extern crate libimagstore;
|
||||||
|
extern crate libimagutil;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[macro_use] extern crate is_match;
|
||||||
|
|
||||||
|
pub mod datepath;
|
||||||
|
pub mod datetime;
|
||||||
|
pub mod error;
|
||||||
|
pub mod range;
|
||||||
|
pub mod result;
|
||||||
|
|
111
libimagentrydatetime/src/range.rs
Normal file
111
libimagentrydatetime/src/range.rs
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
//
|
||||||
|
// imag - the personal information management suite for the commandline
|
||||||
|
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; version
|
||||||
|
// 2.1 of the License.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Error types for range module
|
||||||
|
pub mod error {
|
||||||
|
generate_error_module!(
|
||||||
|
generate_error_types!(DateTimeRangeError, DateTimeRangeErrorKind,
|
||||||
|
EndDateTimeBeforeStartDateTime => "End datetime is before start datetime"
|
||||||
|
);
|
||||||
|
);
|
||||||
|
|
||||||
|
pub use self::error::DateTimeRangeError;
|
||||||
|
pub use self::error::DateTimeRangeErrorKind;
|
||||||
|
pub use self::error::MapErrInto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Result type for range module
|
||||||
|
pub mod result {
|
||||||
|
use std::result::Result as RResult;
|
||||||
|
use super::error::DateTimeRangeError;
|
||||||
|
|
||||||
|
pub type Result<T> = RResult<T, DateTimeRangeError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
use chrono::naive::datetime::NaiveDateTime;
|
||||||
|
use libimagerror::into::IntoError;
|
||||||
|
use self::result::Result;
|
||||||
|
|
||||||
|
/// A Range between two dates
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct DateTimeRange(NaiveDateTime, NaiveDateTime);
|
||||||
|
|
||||||
|
impl DateTimeRange {
|
||||||
|
|
||||||
|
/// Create a new DateTimeRange object
|
||||||
|
///
|
||||||
|
/// # Return value
|
||||||
|
///
|
||||||
|
/// Ok(DateTimeRange) if start is before end,
|
||||||
|
/// else Err(DateTimeRangeError)
|
||||||
|
///
|
||||||
|
pub fn new(start: NaiveDateTime, end: NaiveDateTime) -> Result<DateTimeRange> {
|
||||||
|
use self::error::DateTimeRangeErrorKind as DTREK;
|
||||||
|
if start < end {
|
||||||
|
Ok(DateTimeRange(start, end))
|
||||||
|
} else {
|
||||||
|
Err(DTREK::EndDateTimeBeforeStartDateTime.into_error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use chrono::naive::datetime::NaiveDateTime;
|
||||||
|
use chrono::naive::date::NaiveDate;
|
||||||
|
use chrono::naive::time::NaiveTime;
|
||||||
|
|
||||||
|
use super::DateTimeRange;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_new_returns_error_if_start_after_end_date() {
|
||||||
|
let start = NaiveDateTime::new(
|
||||||
|
NaiveDate::from_ymd(2000, 02, 02),
|
||||||
|
NaiveTime::from_hms(12, 00, 02)
|
||||||
|
);
|
||||||
|
|
||||||
|
let end = NaiveDateTime::new(
|
||||||
|
NaiveDate::from_ymd(2000, 02, 02),
|
||||||
|
NaiveTime::from_hms(12, 00, 01)
|
||||||
|
);
|
||||||
|
|
||||||
|
let res = DateTimeRange::new(start, end);
|
||||||
|
|
||||||
|
assert!(res.is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_new_returns_ok_if_start_is_before_end() {
|
||||||
|
let start = NaiveDateTime::new(
|
||||||
|
NaiveDate::from_ymd(2000, 02, 02),
|
||||||
|
NaiveTime::from_hms(12, 00, 01)
|
||||||
|
);
|
||||||
|
|
||||||
|
let end = NaiveDateTime::new(
|
||||||
|
NaiveDate::from_ymd(2000, 02, 02),
|
||||||
|
NaiveTime::from_hms(12, 00, 02)
|
||||||
|
);
|
||||||
|
|
||||||
|
let res = DateTimeRange::new(start, end);
|
||||||
|
|
||||||
|
assert!(res.is_ok());
|
||||||
|
}
|
||||||
|
}
|
25
libimagentrydatetime/src/result.rs
Normal file
25
libimagentrydatetime/src/result.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
//
|
||||||
|
// imag - the personal information management suite for the commandline
|
||||||
|
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; version
|
||||||
|
// 2.1 of the License.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
//
|
||||||
|
|
||||||
|
use std::result::Result as RResult;
|
||||||
|
|
||||||
|
use error::DateError;
|
||||||
|
|
||||||
|
pub type Result<T> = RResult<T, DateError>;
|
||||||
|
|
Loading…
Reference in a new issue