定义类型为 TimeZone 的变量。

huangapple go评论58阅读模式
英文:

Define variable of type TimeZone

问题

以下是您要求的代码部分的翻译:

// 原始代码
use chrono_tz::Tz;
use chrono::{TimeZone, NaiveDate};
use arrow2::temporal_conversions::parse_offset;

fn my_func(tz: &str) -> () {
    let ndt = NaiveDate::from_ymd_opt(2018, 9, 28).unwrap().and_hms_opt(2, 30, 0).unwrap();
    match parse_offset(&tz) {
        Ok(time_zone) => {
            println!("converted: {:?}", time_zone.from_utc_datetime(&ndt));
        },
        Err(_) => match tz.parse::<Tz>() {
            Ok(time_zone) => {
                println!("converted: {:?}", time_zone.from_utc_datetime(&ndt));
            }
            Err(error) => panic!("Problem opening the file: {:?}", error)
        },
    };
}

fn main() {
    let time_zone = "Asia/Seoul";
    my_func(&time_zone);
}

// 重构后的代码
use chrono_tz::Tz;
use chrono::{TimeZone, NaiveDate};
use arrow2::temporal_conversions::parse_offset;

fn my_func(tz: &str) -> () {
    let ndt = NaiveDate::from_ymd_opt(2018, 9, 28).unwrap().and_hms_opt(2, 30, 0).unwrap();
    let parsed_time_zone: Tz = match parse_offset(&tz) {
        Ok(time_zone) => {
            time_zone
        },
        Err(_) => match tz.parse::<Tz>() {
            Ok(time_zone) => {
                time_zone
            }
            Err(error) => panic!("Problem opening the file: {:?}", error)
        },
    };
    println!("converted: {:?}", parsed_time_zone.from_utc_datetime(&ndt));
}

fn main() {
    let time_zone = "Asia/Seoul";
    my_func(&time_zone);
}

希望这对您有所帮助。如果您有其他问题,请随时提问。

英文:

The following compiles and runs fine:

use chrono_tz::Tz;
use chrono::{TimeZone, NaiveDate};
use arrow2::temporal_conversions::parse_offset;

fn my_func(tz: &amp;str) -&gt; (){
    let ndt = NaiveDate::from_ymd_opt(2018, 9, 28).unwrap().and_hms_opt(2, 30, 0).unwrap();
    match parse_offset(&amp;tz) {
        Ok(time_zone) =&gt; {
            println!(&quot;converted: {:?}&quot;, time_zone.from_utc_datetime(&amp;ndt));
        },
        Err(_) =&gt; match tz.parse::&lt;Tz&gt;() {
            Ok(time_zone) =&gt; {
                println!(&quot;converted: {:?}&quot;, time_zone.from_utc_datetime(&amp;ndt));
            }
            Err(error) =&gt; panic!(&quot;Problem opening the file: {:?}&quot;, error)
        },
    };
}


fn main() {
    let time_zone = &quot;Asia/Seoul&quot;;
    my_func(&amp;time_zone);
}

Noticed though that I'm doing

println!(&quot;converted: {:?}&quot;, time_zone.from_utc_datetime(&amp;ndt));

twice.

I've tried refactoring to

use chrono_tz::Tz;
use chrono::{TimeZone, NaiveDate};
use arrow2::temporal_conversions::parse_offset;

fn my_func(tz: &amp;str) -&gt; (){
    let ndt = NaiveDate::from_ymd_opt(2018, 9, 28).unwrap().and_hms_opt(2, 30, 0).unwrap();
    let parsed_time_zone: TimeZone = match parse_offset(&amp;tz) {
        Ok(time_zone) =&gt; {
            time_zone
        },
        Err(_) =&gt; match tz.parse::&lt;Tz&gt;() {
            Ok(time_zone) =&gt; {
                time_zone
            }
            Err(error) =&gt; panic!(&quot;Problem opening the file: {:?}&quot;, error)
        },
    };
    println!(&quot;converted: {:?}&quot;, parsed_time_zone.from_utc_datetime(&amp;ndt));
}


fn main() {
    let time_zone = &quot;Asia/Seoul&quot;;
    my_func(&amp;time_zone);
}

and get a long error:

error[E0782]: trait objects must include the `dyn` keyword
 --&gt; src/main.rs:7:27
  |
7 |     let parsed_time_zone: TimeZone = match parse_offset(&amp;tz) {
  |                           ^^^^^^^^
  |
help: add `dyn` keyword before this trait
  |
7 |     let parsed_time_zone: dyn TimeZone = match parse_offset(&amp;tz) {
  |                           +++

error[E0191]: the value of the associated type `Offset` (from trait `TimeZone`) must be specified
 --&gt; src/main.rs:7:27
  |
7 |     let parsed_time_zone: TimeZone = match parse_offset(&amp;tz) {
  |                           ^^^^^^^^ help: specify the associated type: `TimeZone&lt;Offset = Type&gt;`

error[E0038]: the trait `TimeZone` cannot be made into an object
 --&gt; src/main.rs:7:27
  |
7 |     let parsed_time_zone: TimeZone = match parse_offset(&amp;tz) {
  |                           ^^^^^^^^ `TimeZone` cannot be made into an object
  |
  = note: the trait cannot be made into an object because it requires `Self: Sized`
  = note: for a trait to be &quot;object safe&quot; it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit &lt;https://doc.rust-lang.org/reference/items/traits.html#object-safety&gt;

error[E0308]: mismatched types
 --&gt; src/main.rs:9:13
  |
9 |             time_zone
  |             ^^^^^^^^^ expected trait object `dyn TimeZone`, found struct `FixedOffset`
  |
  = note: expected trait object `dyn TimeZone`
                   found struct `FixedOffset`

error[E0308]: mismatched types
  --&gt; src/main.rs:13:17
   |
13 |                 time_zone
   |                 ^^^^^^^^^ expected trait object `dyn TimeZone`, found enum `Tz`
   |
   = note: expected trait object `dyn TimeZone`
                      found enum `Tz`

error: the `from_utc_datetime` method cannot be invoked on a trait object
   --&gt; src/main.rs:18:50
    |
18  |     println!(&quot;converted: {:?}&quot;, parsed_time_zone.from_utc_datetime(&amp;ndt));
    |                                                  ^^^^^^^^^^^^^^^^^
    |
   ::: /home/marcogorelli/.cargo/registry/src/github.com-1ecc6299db9ec823/chrono-0.4.23/src/offset/mod.rs:205:21
    |
205 | pub trait TimeZone: Sized + Clone {
    |                     ----- this has a `Sized` requirement

Some errors have detailed explanations: E0038, E0191, E0308, E0782.
For more information about an error, try `rustc --explain E0038`.
error: could not compile `tmp` due to 6 previous errors

I've tried the suggestion to do

let parsed_time_zone: dyn TimeZone = match parse_offset(&amp;tz) {

but then it still errors with

error[E0191]: the value of the associated type `Offset` (from trait `TimeZone`) must be specified
 --&gt; src/main.rs:7:31
  |
7 |     let parsed_time_zone: dyn TimeZone = match parse_offset(&amp;tz) {
  |                               ^^^^^^^^ help: specify the associated type: `TimeZone&lt;Offset = Type&gt;`

How can I just parse tz as TimeZone, without specified whether it's Tz or FixedOffset, and then use it in the rest of the function?

答案1

得分: 1

你无法轻松重构这部分。Rust 是强类型语言,而你的两个 time_zone 变量不是相同的类型。一个是 chrono::FixedOffset,另一个是 chrono_tz::Tz

如果你确实想将它们都存储在同一个变量中,你有两种可能性:

  • 特质对象引用 (&dyn TimeZone)
  • 包装的特质对象 (Box<dyn TimeZone>).

dyn Timezone 本身不能直接成为变量的类型。它没有已知的大小,因为它可以是任何实际大小的类型。因此,你需要使用上述其中一种间接方法。

然而,对于你的情况来说,这两种方法都不太理想:

  • &dyn TimeZone 不起作用,因为必须有某个拥有实际对象的人。你不能返回对内部范围变量的引用,因为它比引用更早被丢弃。
  • Box<dyn TimeZone> 可以工作,没有问题,但它会引入开销:它会在堆上分配实际对象的空间。正如前面所描述的,dyn 对象没有已知的大小。因此,使用 Box,实际对象被移到堆上,在堆栈上的是 Box 对象,它有已知的大小。

所以我建议的做法是:不要担心。你在这里的代码重复非常小。我不认为值得麻烦。


我在回答这个问题后注意到的进一步细节:

  • TimeZone: Sized,这意味着它不是对象安全,并且完全不允许使用 dyn TimeZone。因此,甚至 Box<dyn TimeZone> 也不会起作用。
英文:

You can't refactor this easily. Rust is strongly typed, and your two time_zone variables aren't the same type. One is chrono::FixedOffset, the other is chrono_tz::Tz.

If you do want to store both of them in the same variable, you have two possibilities:

  • trait object references (&amp;dyn TimeZone)
  • Boxed trait objects (Box&lt;dyn TimeZone).

dyn Timezone itself cannot directly be the type of a variable. It doesn't have a known size, because it could be any actual type of any size. Therefore you need one of the indirections above.

Both are non-ideal for your case though:

  • &amp;dyn TimeZone won't work because someone has to own the actual object. You can't return a reference to a variable of an inner scope, as it gets dropped earlier than the reference does.
  • Box&lt;dyn TimeZone&gt; would work, no problem, but it introduces overhead: It will cause a heap allocation where the actual object will be put. The reason, as described earlier, is that a dyn object doesn't have a known size. Therefore, with Box, the actual object gets moved to the heap, and on the stack is the Box object, which has a known size.

So what I would do is: don't worry. The code duplication you have here is really minimal. I don't think it's worth the trouble.


Further detail I noticed after I wrote this answer:

  • TimeZone is : Sized, which means it isn't object safe and dyn TimeZone is disallowed entirely. So not even Box&lt;dyn TimeZone&gt; would work.

huangapple
  • 本文由 发表于 2023年2月6日 20:15:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/75361198.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定