是否可以根据从另一个 UTC 日期时间获取的日期并结合时间字符串和时区字符串来创建 UTC 日期时间?

问题描述 投票:0回答:1

考虑程序的以下输入:

  • 时间=
    18:00
  • timezone =
    Europe/London
    (或时区的任何合理表示,可能的示例包括
    Europe__London
    Europe.London
    等...请参阅注释)
  • 日期,可以通过从
    chrono::Utc::now()
    中去掉日期字段来获得。

是否可以将这些数据或类似的数据组合成一个

chrono::Datetime
对象?

注意:字符串的具体形式并不是特别重要,可以改变。该数据仅来自文本文件。

我认为可能有两种可能的方法。

  • 使用
    format!
    构造 rfc3339 格式的字符串表示形式,然后使用 datetime
    parse_from_rfc3339
    函数对其进行解析。这似乎是错误的方法 - 创建更大的字符串然后解析它们感觉像是一种低效或“笨拙”的方法。不过好像比较容易做到。
  • 我对第二个选项不太有信心。我猜想有一种方法可以直接对某些 chrono 类型进行操作,以从这 3 个部分中的每一个创建日期时间。但对于这个选项,我有点迷失,不知道如何以这种方式解决问题。

到目前为止我的尝试:


选项 1:处理字符串

可以使用 rfc3339 格式的字符串构造

chrono::DateTime
对象。以下是如何做到这一点:

let datetime_rfc3339_format_string =
    format!("{}T{}-{}",
        date_string, time_string, timezone_string);

let datetime_remote = chrono::DateTime::parse_from_rfc3339(datetime_remote_rfc3339_format);

问题就变成了如何以字符串格式构建这三个组件。

时区字符串

我之前设法想出了一种从字符串构造

chrono_tz::Tz
对象的方法。请参阅以下链接问题

let chrono_timezone = Tz::from_str(timezone.as_str())
    .expect("failed to convert string to chrono tz");

这是可行的,假设字符串的格式如下:

Europe/London

但是为了使用 rfc3339 格式的内容,我们需要将这个“时区名称”转换为“小时数偏移”。这既取决于全球日期日期,也取决于夏令时等当地规则。

所以我在这里陷入困境。我不知道如何将

Tz
对象转换为以小时为单位的偏移量,这原则上取决于当前日期。

日期字符串

这部分比较简单。我们可以从

Utc::now()
构建一个 DateTime 对象,并使用
date_naive()
提取日期。然后可以将其格式化为字符串。

let datetime = chrono::Utc::now();
let date = datetime.date_naive();
let string_date = format!("{}", date);

时间字符串

我已经有了所需(字符串)格式的这些。例如,我可以从文本文件中读取这些内容,它们的格式例如:

08:00

选项2:

由于我已经有一个时区对象,所以我的想法是可以使用它直接构造一个 DateTime 对象。看起来

FixedOffset
类型有
with_ymd_and_hms
功能

这表明可以通过某种方式从 Timezone 对象构造 DateTime 对象,并使用我可以访问的附加信息。

但是,这就是我陷入困境的地方。我不知道如何继续这里,或者即使

FixedOffset
是我想要使用的类型。我不知道它与
Tz
有什么关系,如果有的话。

let chrono_timezone = Tz::from_str(timezone.as_str())
    .expect("failed to convert string to chrono tz");
date datetime rust timezone
1个回答
0
投票

这个答案演示了选项 1 的解决方案:

使用这个问题中提供的信息,我们可以解决如何将时区转换为偏移量的问题,然后将其转换为所需的字符串格式。

fn get_todays_offset(tz: chrono_tz::Tz) -> chrono::Duration {

    let now = chrono::Utc::now().naive_utc();
    let offset = tz.offset_from_utc_datetime(&now);
    offset.base_utc_offset() + offset.dst_offset()
}

fn get_todays_offset_as_hh_mm(tz: chrono_tz::Tz) -> String {

    let todays_offset = get_todays_offset(tz);
    
    let todays_offset_sign = todays_offset.num_nanoseconds().unwrap().signum();
    let todays_offset_hours = todays_offset.num_hours();
    let todays_offset_minutes = todays_offset.num_minutes() % 60;

    let mut todays_offset_hh_mm_string = format!("{:02}:{:02}", todays_offset_hours, todays_offset_minutes);
    if todays_offset_sign >= 0 {
        todays_offset_hh_mm_string = format!("+{}", todays_offset_hh_mm_string);
    }
    else {
        todays_offset_hh_mm_string = format!("-{}", todays_offset_hh_mm_string);
    }
    
    return todays_offset_hh_mm_string;
}

由此,我们可以构造 rfc3339 字符串。

let timezone_string = get_todays_offset_as_hh_mm(tz);

let datetime_rfc3339_format =
    format!("{}T{}-{}",
        date_string, time_string, timezone_string);

let datetime =
    chrono::DateTime::parse_from_rfc3339(
        datetime_remote_rfc3339_format.as_str())
            .expect("rfc3339 parse failed");
© www.soinside.com 2019 - 2024. All rights reserved.