首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何静态地将` `chrono::format::strftime`‘转换为` `chrono::format::Item`?

如何静态地将` `chrono::format::strftime`‘转换为` `chrono::format::Item`?
EN

Stack Overflow用户
提问于 2018-02-25 16:03:35
回答 1查看 585关注 0票数 3

我的应用程序支持一个静态的chrono::format::strftime格式数组。我希望避免在运行时解析它们,所以我定义了一个lazy_static!块,它将它们解析为chrono::format::Item的集合。

但是,当我试图迭代分析过的集合时,我会得到一个错误:

代码语言:javascript
复制
the trait bound `&chrono::format::StrftimeItems<'_>: std::iter::Iterator` is not satisfied

这里有一个简短的复制:

代码语言:javascript
复制
#[macro_use]
extern crate lazy_static;
extern crate chrono;
use chrono::DateTime;
use chrono::offset::FixedOffset;
use chrono::format::{Parsed, parse};
use chrono::format::strftime::StrftimeItems;

static FORMATS : &[&'static str] = &["%Y-%m-%dT%H:%M:%S", "%Y-%m-%dT%H:%M:%S%.f"];

lazy_static! {
    static ref PARSED_FORMATS : Vec<StrftimeItems<'static>> = FORMATS
        .iter()
        .map(|format| StrftimeItems::new(format))
        .collect();
}

fn parse_datetime(s: &str) -> Option<DateTime<FixedOffset>> {
    for format in PARSED_FORMATS.iter() {
        let mut parsed = Parsed::new();
        let dt = parse(&mut parsed, &s, format)
            .and_then(|_| parsed.to_datetime() );
        if dt.is_ok() {
            return dt.ok()
        }
    }
    return None
}

试图在循环中取消引用format会导致以下错误:

代码语言:javascript
复制
error[E0507]: cannot move out of borrowed content
  --> src\main.rs:21:35
   |
21 |         let dt = parse(&mut parsed, &s, *format)
   |                                         ^^^^^^^ cannot move out of borrowed content

error: aborting due to previous error

尝试克隆format似乎是可行的,但是这里的克隆似乎是多余的,我想避免它。

这是正确的方法吗?还是使用宏是更好的选择?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-02-25 16:25:24

StrftimeItems是一个迭代器,而不是一个可迭代的容器(就像Vec那样)。当您推进迭代器时,您不能将其倒带。parse必须通过值接收迭代器,这意味着必须接受向量的StrftimeItems (这意味着以后不能重用它),或者克隆存储在向量中的StrftimeItems。通过克隆StrftimeItems,您可以生成一个新的迭代器,它的状态不同于原始的迭代器(即前进的一个不会提前另一个)。

我希望避免在运行时解析它们。

但是,StrftimeItems不允许您实现您的目标,因为 lazily parses the format string as the iterator advances

相反,我建议您将迭代器的结果收集到Vec<Item<'static>>中。

代码语言:javascript
复制
#[macro_use]
extern crate lazy_static;
extern crate chrono;
use chrono::DateTime;
use chrono::offset::FixedOffset;
use chrono::format::{Item, Parsed, parse};
use chrono::format::strftime::StrftimeItems;

static FORMATS : &[&'static str] = &["%Y-%m-%dT%H:%M:%S", "%Y-%m-%dT%H:%M:%S%.f"];

lazy_static! {
    static ref PARSED_FORMATS : Vec<Vec<Item<'static>>> = FORMATS
        .iter()
        .map(|format| StrftimeItems::new(format).collect())
        .collect();
}

fn parse_datetime(s: &str) -> Option<DateTime<FixedOffset>> {
    for format in PARSED_FORMATS.iter() {
        let mut parsed = Parsed::new();
        let dt = parse(&mut parsed, &s, format.iter().cloned())
            .and_then(|_| parsed.to_datetime() );
        if dt.is_ok() {
            return dt.ok()
        }
    }
    return None
}

现在,当我们调用parse时,我们传递format.iter().cloned()format是一个Vec<Item<'static>>iter()在对Item的引用上生成一个新的迭代器,并且cloned()对迭代器进行调整,以便每个Item按值返回(通过克隆它们来实现),而不是通过引用(因为parse期望迭代器在Item值上,而不是Item引用)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48975507

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档