How to localize chrono days? - rust

I have a code https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=cde949e0a59445ee9beb01964a3ab903
use chrono::Datelike;
use chrono::Duration;
use chrono::Local;
fn main() {
let now = Local::now();
println!("######################################");
for day in 0..31 {
println!(
"{}",
(now + Duration::days(7 - now.weekday().num_days_from_monday() as i64 + day))
.format("%Y-%m-%d %A")
);
println!("\ntest\n\n########################");
}
}
Q: Where I need the weekdays to be in ex.: "HU" language and not in the English "Monday, Tuesday", etc.
I already tried based on https://docs.rs/chrono/0.4.19/chrono/ the ", Locale::hu_HU)" but always failed so far, can you pls help on this?

I think you need the feature unstable-locales for this. See here for the usage of format_localized.

Related

how to get the timestamp with timezone in rust

I am using this rust code to get the timestamp, but the time without time zone:
use std::time::Duration;
use chrono::{DateTime, FixedOffset, Local, NaiveDateTime, TimeZone, Utc};
use diesel::sql_types::Timestamptz;
use rust_wheel::common::util::time_util::get_current_millisecond;
use tokio::time;
#[tokio::main]
async fn main() {
let trigger_time = (get_current_millisecond() - 35000)/1000;
let time_without_zone = NaiveDateTime::from_timestamp( trigger_time ,0);
}
the timestamp result is 2022-08-30 13:00:15, the actual wanted result is: 2022-08-30 21:00:15. Then I tried to set the timezone:
use std::time::Duration;
use chrono::{DateTime, FixedOffset, Local, NaiveDateTime, TimeZone, Utc};
use diesel::sql_types::Timestamptz;
use rust_wheel::common::util::time_util::get_current_millisecond;
use tokio::time;
#[tokio::main]
async fn main() {
let trigger_time = (get_current_millisecond() - 35000)/1000;
let time_without_zone = NaiveDateTime::from_timestamp( trigger_time ,0);
let tz_offset = FixedOffset::east(8 * 3600);
let date_time: DateTime<Local> = Local.from_local_datetime(&time_without_zone).unwrap();
print!("{}",date_time);
let dt_with_tz: DateTime<FixedOffset> = tz_offset.from_local_datetime(&time_without_zone).unwrap();
print!("{}",dt_with_tz);
}
the result is 2022-08-30 13:00:15 +08:00. is it possible to get the timestamp with the timezone? what should I do? I mean get the timestamp format like this 2022-08-30 21:00:15.
the result is 2022-08-30 13:00:15 +08:00. is it possible to get the timestamp with the timezone? what should I do? I mean get the timestamp format like this 2022-08-30 21:00:15.
Your timestamp is (I assume) UTC, so that's what you should tell Chrono:
let time_without_zone = NaiveDateTime::from_timestamp(timestamp, 0);
// 2009-02-13 23:31:30
let zoned: DateTime<FixedOffset> = DateTime::from_utc(time_without_zone, FixedOffset::east(8 * 3600));
// 2009-02-14 07:31:30 +08:00
Then you can use naive_local() to get a naive (timezone-less) view of the local time:
zoned.naive_local()
2009-02-14 07:31:30
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=941668e1e10930b0e9a6ede7e79fb0c1
Warning: I'm not entirely sure naive_local() is the correct call, normally in chrono the "local" timezone is the timezone configured for the machine the program runs on (or something along those lines), but for naive_local it seems like chrono just applies the timezone and returns the result as a naive datetime. So it's what you want, but I find it a bit dubious. I can't find a better call tho.

is it possible using rust to generate jsx AST?

I'm not familiar with rust and trynna using swc to replace the babel
but I found #swc/core doesn't offer the api to generate code AST, so I want to write one using rust, is it possible to generate jsx ast?
Here is a good place to start: https://github.com/swc-project/swc/blob/main/crates/swc_ecma_parser/examples/typescript.rs
but link can get invalid so I also pasted the code:
use swc_common::{
self,
errors::{ColorConfig, Handler},
sync::Lrc,
FileName, SourceMap,
};
use swc_ecma_parser::{lexer::Lexer, Capturing, Parser, StringInput, Syntax};
fn main() {
let cm: Lrc<SourceMap> = Default::default();
let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(cm.clone()));
// Real usage
// let fm = cm
// .load_file(Path::new("test.js"))
// .expect("failed to load test.js");
let fm = cm.new_source_file(
FileName::Custom("test.js".into()),
"interface Foo {}".into(),
);
let lexer = Lexer::new(
Syntax::Typescript(Default::default()),
Default::default(),
StringInput::from(&*fm),
None,
);
let capturing = Capturing::new(lexer);
let mut parser = Parser::new_from(capturing);
for e in parser.take_errors() {
e.into_diagnostic(&handler).emit();
}
let _module = parser
.parse_typescript_module()
.map_err(|e| e.into_diagnostic(&handler).emit())
.expect("Failed to parse module.");
println!("Tokens: {:?}", parser.input().take());
}
I never really worked or cared about this. All it took was 5min of browsing the repository, all the resources are there but if you are new to rust, I recommend the rust book first.

What is the idiomatic way to do something when an Option is either None, or the inner value meets some condition?

Is there a more idiomatic way to express something like the following?
fn main() {
let mut foo: Option<u8> = None;
match foo {
Some(foo_val) if ! (foo_val < 5) /* i.e. the negation of my acceptance condition */ => {}
_ => { foo.replace(5); }
}
}
It seems like most of the time there's an alternative to having an arm that doesn't do anything, but I've been unable to find one for this particular case.
What I'd like to say is the more direct if foo.is_none() || /* some way to extract and test the inner value */ { ... }, or perhaps some chaining trick that's eluding me.
// in None case
// │ in Some(_) case
// ┌┴─┐ ┌───────────────────┐
if foo.map_or(true, |foo_val| foo_val < 5) {
// ...
}
For more information see Option::map_or.
There are many ways to do it. One of the simplest (and arguably most readable) is something like this:
if foo.unwrap_or(0) < 5 {
...
}
The above will be true in both cases:
when foo is Some with a value smaller than 5;
when foo is None.
In some more complex scenarios, where the "default" value needs to be calculated and performance is critical, you might want to consider unwrap_or_else.
As Lukas suggested, the map_or method can also be used. Note that arguments passed to map_or are eagerly evaluated, so if performance is critical, you might want to consider map_or_else as an alternative.
You can do it with filter (using the negation of your condition) and is_none:
if foo.filter(|&x| !(x < 5)).is_none() {
// Here either foo was None or it contained a value less than 5
}
I'm not sure I completely understand your question but you can try something like that:
fn main() {
let foo: Option<u8> = None;
let result = foo.filter(|foo_val| !(*foo_val < 5) ).unwrap_or(5);
println!("Result: {result}");
}
More example on Playground
The matches! macro seems like a good fit:
if !matches!(foo, Some(a) if a>=5) { foo.replace(5) }
Rust Playground
I'll throw in another solution just for fun....
foo = foo.
or(Some(5)). // if None return Some(5)
map(|x| if x<5 { 5 } else { x });
or (for this specific example)
foo = foo.
or(Some(5)). // if None return Some(5)
map(|x| u8::max(x, 5));
With filter and or,
foo = foo.filter(|a| *a >= 5)
.or(Some(5));
There is the unstable method Option::is_some_and that has been built for exactly this purpose:
if foo.is_some_and(|foo_val| foo_val < 5) {
// ...
}
As it's unstable, it's currently only usable on nightly. See the tracking issue for up to date information.

Does Rust 2018 support "if let" chaining?

I'm parsing a vector of tokens, each of enum type. This means I get a lot of code like:
if v.len() >= 3 {
if let Token::Type1(value1) = &v[0] {
if let Token::Type2(value2) = &v[1] {
if let Token::Type(value3) = &v[2] {
return Parsed123(value1, value2, value3);
}
}
}
}
This is pretty ugly - and I've worked out that I can do this to make it a little nicer:
if v.len() >= 3 {
if let (Token::Type1(value1), Token::Type2(value2), Token::Type3(value3)) =
(&v[0], &v[1], &v[2])
{
return Parsed123(value1, value2, value3);
}
}
But honestly, its not much better.
However, there's some closed issues / RFCs for chaining these conditions and "if let" bits in what feels a lot more ergonomic way -- Tracking issue for eRFC 2497 "if- and while-let-chains take 2" and Support && in if let expressions -- this would let me write something like:
if v.len() >= 3 &&
let Token::Type1(value1) = &v[0] &&
let Token::Type2(value2) = &v[1] &&
let Token::Type3(value3) = &v[2]
{
return Parsed123(value1, value2, value3);
}
However, I can't seem to get this to compile in my copy of nightly Rust with edition="2018" (exact version is 1.32.0-nightly (653da4fd0 2018-11-08)). So either I've got the syntax wrong or I've misinterpreted the RFCs / issues and this feature hasn't landed yet. Either way, I'd love some info on how this feature stands.
RFC #2497 has not been implemented yet. The GitHub issue you linked is only for describing how to deal with the ambiguity.
To enable the second interpretation in the previous section a warning must be emitted in Rust 2015 informing the user that [...] will both become hard errors, in the first version of Rust where the 2018 edition is stable, without the let_chains features having been stabilized.
So no, you cannot use the syntax yet, but instead use tuples as a workaround, as you already did.
if v.len() >= 3 {
if let (Token::Type1(value1), Token::Type2(value2), Token::Type3(value3)) =
(&v[0], &v[1], &v[2])
{
return Parsed123(value1, value2, value3);
}
}
While hellow is correct that RFC #2497 is not yet supported in 2018 (and 2015), I felt the if_chain library mentioned by Michail was worthy of an answer.
The if_chain library provides a macro that transforms some code that is almost in the form of RFC #2497 into valid Rust.
You can write:
if_chain! {
if v.len() >= 3;
if let Token::Type1(value1) = &v[0];
if let Token::Type2(value2) = &v[1];
if let Token::Type3(value3) = &v[2];
then {
return Parsed123(value1, value2, value3);
}
}
which the compiler treats as:
if v.len() >= 3 {
if let Token::Type1(value1) = &v[0] {
if let Token::Type2(value2) = &v[1] {
if let Token::Type(value3) = &v[2] {
return Parsed123(value1, value2, value3);
}
}
}
}
As mentioned in the comments by L.F., in 2020 there is now another alternative. It still doesn't give us chained if let, but does allow us to match on slices - which is enough to make this example quite neat. The code could now be written as
if let [Token::Type1(value1), Token::Type2(value2), Token::Type3(value3), ..] = v {
return Parsed123(value1, value2, value);
}

Why is this hashmap search slower than expected?

What is the best way to check a hash map for a key?
Currently I am using this:
let hashmap = HashMap::<&str, &str>::new(); // Empty hashmap
let name = "random";
for i in 0..5000000 {
if !hashmap.contains_key(&name) {
// Do nothing
}
}
This seems to be fast in most cases and takes 0.06 seconds when run as shown, but when I use it in this following loop it becomes very slow and takes almost 1 min on my machine. (This is compiling with cargo run --release).
The code aims to open an external program, and loop over the output from that program.
let a = vec!["view", "-h"]; // Arguments to open process with
let mut child = Command::new("samtools").args(&a)
.stdout(Stdio::piped())
.spawn()
.unwrap();
let collect_pairs = HashMap::<&str, &str>::new();
if let Some(ref mut stdout) = child.stdout {
for line in BufReader::new(stdout).lines() {
// Do stuff here
let name = "random";
if !collect_pairs.contains_key(&name) {
// Do nothing
}
}
}
For some reason adding the if !collect_pairs.contains_key( line increases the run time by almost a minute. The output from child is around 5 million lines. All this code exists in fn main()
EDIT
This appears to fix the problem, resulting in a fast run time, but I do not know why the !hashmap.contains_key does not work well here:
let n: Option<&&str> = collect_pairs.get(name);
if match n {Some(v) => 1, None => 0} == 1 {
// Do something
}
One thing to consider is that HashMap<K, V> uses a cryptographically secure hashing algorithm by default, so it will always be a bit slow by nature.
get() boils down to
self.search(k).map(|bucket| bucket.into_refs().1)
contains_key is
self.search(k).is_some()
As such, that get() is faster for you seems strange to me, it's doing more work!
Also,
if match n {Some(v) => 1, None => 0} == 1 {
This can be written more idiomatically as
if let Some(v) = n {
Ive found my problem, Im sorry I didnt pick up until now. I wasnt checking the return of if !collect_pairs.contains_key(&name) properly. It returns true for some reason resulting in the rest of the if block being run. I assumed it was evaluating to false. Thanks for the help

Resources