定义类型为 TimeZone 的变量。

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

Define variable of type TimeZone

问题

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

  1. // 原始代码
  2. use chrono_tz::Tz;
  3. use chrono::{TimeZone, NaiveDate};
  4. use arrow2::temporal_conversions::parse_offset;
  5. fn my_func(tz: &str) -> () {
  6. let ndt = NaiveDate::from_ymd_opt(2018, 9, 28).unwrap().and_hms_opt(2, 30, 0).unwrap();
  7. match parse_offset(&tz) {
  8. Ok(time_zone) => {
  9. println!("converted: {:?}", time_zone.from_utc_datetime(&ndt));
  10. },
  11. Err(_) => match tz.parse::<Tz>() {
  12. Ok(time_zone) => {
  13. println!("converted: {:?}", time_zone.from_utc_datetime(&ndt));
  14. }
  15. Err(error) => panic!("Problem opening the file: {:?}", error)
  16. },
  17. };
  18. }
  19. fn main() {
  20. let time_zone = "Asia/Seoul";
  21. my_func(&time_zone);
  22. }
  23. // 重构后的代码
  24. use chrono_tz::Tz;
  25. use chrono::{TimeZone, NaiveDate};
  26. use arrow2::temporal_conversions::parse_offset;
  27. fn my_func(tz: &str) -> () {
  28. let ndt = NaiveDate::from_ymd_opt(2018, 9, 28).unwrap().and_hms_opt(2, 30, 0).unwrap();
  29. let parsed_time_zone: Tz = match parse_offset(&tz) {
  30. Ok(time_zone) => {
  31. time_zone
  32. },
  33. Err(_) => match tz.parse::<Tz>() {
  34. Ok(time_zone) => {
  35. time_zone
  36. }
  37. Err(error) => panic!("Problem opening the file: {:?}", error)
  38. },
  39. };
  40. println!("converted: {:?}", parsed_time_zone.from_utc_datetime(&ndt));
  41. }
  42. fn main() {
  43. let time_zone = "Asia/Seoul";
  44. my_func(&time_zone);
  45. }

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

英文:

The following compiles and runs fine:

  1. use chrono_tz::Tz;
  2. use chrono::{TimeZone, NaiveDate};
  3. use arrow2::temporal_conversions::parse_offset;
  4. fn my_func(tz: &amp;str) -&gt; (){
  5. let ndt = NaiveDate::from_ymd_opt(2018, 9, 28).unwrap().and_hms_opt(2, 30, 0).unwrap();
  6. match parse_offset(&amp;tz) {
  7. Ok(time_zone) =&gt; {
  8. println!(&quot;converted: {:?}&quot;, time_zone.from_utc_datetime(&amp;ndt));
  9. },
  10. Err(_) =&gt; match tz.parse::&lt;Tz&gt;() {
  11. Ok(time_zone) =&gt; {
  12. println!(&quot;converted: {:?}&quot;, time_zone.from_utc_datetime(&amp;ndt));
  13. }
  14. Err(error) =&gt; panic!(&quot;Problem opening the file: {:?}&quot;, error)
  15. },
  16. };
  17. }
  18. fn main() {
  19. let time_zone = &quot;Asia/Seoul&quot;;
  20. my_func(&amp;time_zone);
  21. }

Noticed though that I'm doing

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

twice.

I've tried refactoring to

  1. use chrono_tz::Tz;
  2. use chrono::{TimeZone, NaiveDate};
  3. use arrow2::temporal_conversions::parse_offset;
  4. fn my_func(tz: &amp;str) -&gt; (){
  5. let ndt = NaiveDate::from_ymd_opt(2018, 9, 28).unwrap().and_hms_opt(2, 30, 0).unwrap();
  6. let parsed_time_zone: TimeZone = match parse_offset(&amp;tz) {
  7. Ok(time_zone) =&gt; {
  8. time_zone
  9. },
  10. Err(_) =&gt; match tz.parse::&lt;Tz&gt;() {
  11. Ok(time_zone) =&gt; {
  12. time_zone
  13. }
  14. Err(error) =&gt; panic!(&quot;Problem opening the file: {:?}&quot;, error)
  15. },
  16. };
  17. println!(&quot;converted: {:?}&quot;, parsed_time_zone.from_utc_datetime(&amp;ndt));
  18. }
  19. fn main() {
  20. let time_zone = &quot;Asia/Seoul&quot;;
  21. my_func(&amp;time_zone);
  22. }

and get a long error:

  1. error[E0782]: trait objects must include the `dyn` keyword
  2. --&gt; src/main.rs:7:27
  3. |
  4. 7 | let parsed_time_zone: TimeZone = match parse_offset(&amp;tz) {
  5. | ^^^^^^^^
  6. |
  7. help: add `dyn` keyword before this trait
  8. |
  9. 7 | let parsed_time_zone: dyn TimeZone = match parse_offset(&amp;tz) {
  10. | +++
  11. error[E0191]: the value of the associated type `Offset` (from trait `TimeZone`) must be specified
  12. --&gt; src/main.rs:7:27
  13. |
  14. 7 | let parsed_time_zone: TimeZone = match parse_offset(&amp;tz) {
  15. | ^^^^^^^^ help: specify the associated type: `TimeZone&lt;Offset = Type&gt;`
  16. error[E0038]: the trait `TimeZone` cannot be made into an object
  17. --&gt; src/main.rs:7:27
  18. |
  19. 7 | let parsed_time_zone: TimeZone = match parse_offset(&amp;tz) {
  20. | ^^^^^^^^ `TimeZone` cannot be made into an object
  21. |
  22. = note: the trait cannot be made into an object because it requires `Self: Sized`
  23. = 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;
  24. error[E0308]: mismatched types
  25. --&gt; src/main.rs:9:13
  26. |
  27. 9 | time_zone
  28. | ^^^^^^^^^ expected trait object `dyn TimeZone`, found struct `FixedOffset`
  29. |
  30. = note: expected trait object `dyn TimeZone`
  31. found struct `FixedOffset`
  32. error[E0308]: mismatched types
  33. --&gt; src/main.rs:13:17
  34. |
  35. 13 | time_zone
  36. | ^^^^^^^^^ expected trait object `dyn TimeZone`, found enum `Tz`
  37. |
  38. = note: expected trait object `dyn TimeZone`
  39. found enum `Tz`
  40. error: the `from_utc_datetime` method cannot be invoked on a trait object
  41. --&gt; src/main.rs:18:50
  42. |
  43. 18 | println!(&quot;converted: {:?}&quot;, parsed_time_zone.from_utc_datetime(&amp;ndt));
  44. | ^^^^^^^^^^^^^^^^^
  45. |
  46. ::: /home/marcogorelli/.cargo/registry/src/github.com-1ecc6299db9ec823/chrono-0.4.23/src/offset/mod.rs:205:21
  47. |
  48. 205 | pub trait TimeZone: Sized + Clone {
  49. | ----- this has a `Sized` requirement
  50. Some errors have detailed explanations: E0038, E0191, E0308, E0782.
  51. For more information about an error, try `rustc --explain E0038`.
  52. error: could not compile `tmp` due to 6 previous errors

I've tried the suggestion to do

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

but then it still errors with

  1. error[E0191]: the value of the associated type `Offset` (from trait `TimeZone`) must be specified
  2. --&gt; src/main.rs:7:31
  3. |
  4. 7 | let parsed_time_zone: dyn TimeZone = match parse_offset(&amp;tz) {
  5. | ^^^^^^^^ 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:

确定