一个简单的rust字符串时钟
1、简介
用rust写的一个简单的练手的demo,一个字符串时钟,在终端用字符串方式显示当前时间。本质是对图片取灰度,然后每个像素按灰度门限用星号代替灰度值,就把图片变为由星号组成的字符型图案。把时间字符串的每个字符按照字母和数字图片的样式转换为字符,然后拼接字符图案就实现了字符时钟的效果。
主要用到的知识有:rust操作时间、字符串、vector,字符串和vector的转换、string,以及让人恼火的生命周期。对比python,rust的列表入门难度可以说是地狱级的,一会borrow、一会move,晕头转向。

2、用到的知识点
2.1 取utc时间
时间库使用chrono = "0.4",获取秒数等时间。
let five_seconds = Duration::new(5, 0);
let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 10);
assert_eq!(five_seconds_and_five_nanos.as_secs(), 5);
assert_eq!(five_seconds_and_five_nanos.subsec_nanos(), 10);
let five_seconds = Duration::from_secs(5);
assert_eq!(five_seconds, Duration::from_millis(5_000));
assert_eq!(five_seconds, Duration::from_micros(5_000_000));
assert_eq!(five_seconds, Duration::from_nanos(5_000_000_000));
let ten_seconds = Duration::from_secs(10);
let seven_nanos = Duration::from_nanos(7);
let total = ten_seconds + seven_nanos;
assert_eq!(total, Duration::new(10, 7));
获取实时utc时间。
let local:DateTime<Local>= Local::now();
println!("{:?}", local.format("%Y-%m-%d %H:%M:%S").to_string());
println!("{:?}", local.format("%a %b %e %T %Y").to_string());
println!("{:?}", local.format("%c").to_string());
println!("{:?}", local.to_string());
println!("{:?}", local.to_rfc2822());
println!("{:?}", local.to_rfc3339());
let dt = Local.with_ymd_and_hms(2020 as i32, 12, 05, 12, 0, 9).unwrap();
println!("{:?}", dt.format("%Y-%m-%d %H:%M:%S").to_string());
println!("{:?}", dt.format("%a %b %e %T %Y").to_string());
println!("{:?}", dt.format("%c").to_string());
println!("{:?}", dt.to_string());
println!("{:?}", dt.to_rfc2822());
println!("{:?}", dt.to_rfc3339());
输出为:
"2022-12-25 23:20:03"
"Sun Dec 25 23:20:03 2022"
"Sun Dec 25 23:20:03 2022"
"2022-12-25 23:20:03.499293300 +08:00"
"Sun, 25 Dec 2022 23:20:03 +0800"
"2022-12-25T23:20:03.499293300+08:00"
"2020-12-05 12:00:09"
"Sat Dec 5 12:00:09 2020"
"Sat Dec 5 12:00:09 2020"
"2020-12-05 12:00:09 +08:00"
"Sat, 05 Dec 2020 12:00:09 +0800"
"2020-12-05T12:00:09+08:00"
获取当前时间,如下格式化为20:15:23类似的格式。
let curdate = Local::now();
let datecollect = curdate.format("%H:%M:%S").to_string();
2.2 图片变换为像素图案
1、读取图片
先准备每个数字的图片,然后读取图片,转换为灰度表示。

let cur_dir = std::env::current_dir().unwrap().
into_os_string().into_string().unwrap();
let _path = if number == ':' {
format!("{}/number_pic/{}.png", &cur_dir, "maohao")
}
else{
format!("{}/number_pic/{}.png", &cur_dir, number)
};
// println!("imagepath = {}", _path);
let gray_pic = image::open(_path).unwrap()
.resize(nwidth, nheight, image::imageops::FilterType::Nearest)
.into_luma8();
初始化pix_clock结构体,解析需要用到的10个数字和冒号时间分隔字符。
pub struct pix_clock {
words : HashMap<char, Vec<String>>,
}
impl pix_clock {
pub fn new() -> pix_clock {
let mut dict_result = HashMap::new();
let numbers = vec!['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':'];
for value in numbers {
let result = get_num_pic(value);
dict_result.insert(value, result);
// println!("num={} {:#?}", value, dict_result[&value]);
}
return pix_clock {
words: dict_result,
};
}
}
2、图片按像素灰度转换为字符图案
每行作为1个string字符串,按行处理,读取完一行后把当前行的字符串push到列表,然后清空行变量,准备解析下一行的像素。每行都解析完成后,pix_data就形成了一个由nheight行,每行nwidth个字符构成的列表。
let mut pix_data: Vec<String> = vec![];
let mut line = String::from("");
for (index, tmp) in gray_pic.to_vec().iter().enumerate() {
if index % nwidth as usize == 0 {
if line.len()>0 {
let line2 = line.clone();
pix_data.push(line2);
}
line.clear();
}
if tmp > &gap_value {
line.push_str("*");
}
else {
line.push_str(" ");
}
}
以数字3为例:println!("result data {} {:#?}", number, &pix_data);// 输出数据为:
result data 3 [
"*************",
"*************",
"****** ******",
"*** ***",
"*** ***",
"*** *** **",
"******** **",
"******* ***",
"**** ***",
"**** ***",
"******* **",
"******** **",
"********* **",
"** *** **",
"** ***",
"*** ***",
"***** *****",
"*************",
"*************",
]
2.3 字符方式显示当前时间
上一步已经完成了单个数字转换为字符图案,由于时间字符串由多位数字构成,所以需要拼接图案。例如20:15:23,就由6个数字和2个冒号组成,所以字符串“20:15:23”就需要按行合并。
1)合并每个数组的团案,而高度不变。
let time_str = datestr.chars(); // 把字符串解析为char型字符
let mut final_vector: Vec<String> = vec![];
for _index in 0..self.words.get(&'0').unwrap().len() { // 合并后的图案高度不变,即行数不变
final_vector.push("".to_string()); // 每行的字符串变长了,先预留空String来接收每行字符
}
2)按行合并每个字符,拼接字符串的图案
for value in time_str { //遍历时间字符串的每个字符
let value_pix = self.words.get(&value).unwrap(); //获取单个字符的图案
let mut index = 0;
for x in value_pix.iter() {
final_vector[index].push_str(&x); # 每个字符相同行的字符串合并为一个大字符串
index += 1;
}
}
for temp in final_vector { // 合并后的字符串,高度不变(即行数不变)
println!("{}", format!("{}", temp)); // 打印合并后的字符串,按行显示
}
println!("");
2.4 时间刷新
按秒刷新,每秒计算一次图案字符串,然后清屏后显示,实现时间跑秒的感觉。
fn main() {
let pix_clock = pix_clock::new();
let delay = time::Duration::from_secs(1);
loop {
let curdate = Local::now();
let datecollect = curdate.format("%H:%M:%S").to_string();
pix_clock.beautifyshow(&datecollect);
thread::sleep(delay);
Clear(ClearType::All);
}
}

参考文献:
1、特别感谢 https://github.com/yuanzhoulvpi2017/countdown
2、https://docs.rs/chrono/latest/chrono/
一个简单的rust字符串时钟的更多相关文章
- 一个简单的Python字符串处理文件
#!/usr/bin/env python3 import re def lineprocess(line): res = '' index = 47 if line[index] == 'e': i ...
- 一个简单的AXIS远程调用Web Service示例
我们通常都将编写好的Web Service发布在Tomcat或者其他应用服务器上,然后通过浏览器调用该Web Service,返回规范的XML文件.但是如果我们不通过浏览器调用,而是通过客户端程序调用 ...
- SQL点滴3—一个简单的字符串分割函数
原文:SQL点滴3-一个简单的字符串分割函数 偶然在电脑里看到以前保存的这个函数,是将一个单独字符串切分成一组字符串,这里分隔符是英文逗号“,” 遇到其他情况只要稍加修改就好了 CREATE FUN ...
- 一个用于提取简体中文字符串中省,市和区并能够进行映射,检验和简单绘图的python模块
简介 一个用于提取简体中文字符串中省,市和区并能够进行映射,检验和简单绘图的python模块. 举个例子: ["徐汇区虹漕路461号58号楼5楼", "泉州市洛江区万安塘 ...
- C 封装一个通用链表 和 一个简单字符串开发库
引言 这里需要分享的是一个 简单字符串库和 链表的基库,代码也许用到特定技巧.有时候回想一下, 如果我读书的时候有人告诉我这些关于C开发的积淀, 那么会走的多直啊.刚参加工作的时候做桌面开发, 服务是 ...
- 一个简单的字符串,为什么 Redis 要设计的如此特别
Redis 的 9 种数据类型 本文GitHub已收录:https://zhouwenxing.github.io/ Redis 中支持的数据类型到 5.0.5 版本,一共有 9 种.分别是: 1.B ...
- Linux内核分析第三周学习总结:构造一个简单的Linux系统MenuOS
韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.Linux内 ...
- 计算机程序的思维逻辑 (60) - 随机读写文件及其应用 - 实现一个简单的KV数据库
57节介绍了字节流, 58节介绍了字符流,它们都是以流的方式读写文件,流的方式有几个限制: 要么读,要么写,不能同时读和写 不能随机读写,只能从头读到尾,且不能重复读,虽然通过缓冲可以实现部分重读,但 ...
- 用php实现一个简单的链式操作
最近在读<php核心技术与最佳实践>这本书,书中第一章提到用__call()方法可以实现一个简单的字符串链式操作,比如,下面这个过滤字符串然后再求长度的操作,一般要这么写: strlen( ...
- 使用MongoDB和JSP实现一个简单的购物车系统
目录 1 问题描述 2 解决方案 2.1 实现功能 2.2 最终运行效果图 2.3 系统功能框架示意图 2.4 有关MongoDB简介及系统环境配置 2.5 核心功能代码讲解 ...
随机推荐
- 洛谷U81904 【模板】树的直径
有负边权,所以用树形DP来找树的直径. 1 //树形DP求树的直径 2 #include<bits/stdc++.h> 3 using namespace std; 4 const int ...
- 洛谷P2216 HAOI2007 理想的正方形 (单调队列)
题目就是要求在n*m的矩形中找出一个k*k的正方形(理想正方形),使得这个正方形内最值之差最小(就是要维护最大值和最小值),显然我们可以用单调队列维护. 但是二维平面上单调队列怎么用? 我们先对行处理 ...
- python-D1-typora软件和计算机入门1
一 typora软件 typora是一款目前非常火爆文本编辑器 1.1 安装 尽量安装在非系统盘符及设置为短路径,方便后面查找 1.2 文件路径 在计算机上就是一个资源的定位坐标,表现为具体在哪里,例 ...
- day49-JDBC和连接池05
JDBC和连接池05 11.BasicDAO 先来分析一个问题 前面我们使用了Apache-DBUtils和Druid简化了JDBC开发,但仍存在以下不足: SQL语句是固定的,不能通过参数传入,通用 ...
- Springboot+vue 实现汽车租赁系统(毕业设计二)(前后端项目分离)
文章目录 1.系统功能列表 2.管理员端界面 2.1 商家登录界面 2.2 用户信息管理界面 2.3 汽车管理界面 2.4 订单界面 2.5 汽车图形报表 2.6 优惠券新增界面 3.普通用户界面 3 ...
- "一键重装系统软件"操作流程
博主之前重装系统都是直接用win10系统更新里的重置系统(版本不会变化),和U盘重装电脑出厂映像(有各种品牌自带的软件,而且由于是出场版本,版本很低) 所以这次用"小白一键重装系统" ...
- JS 可编辑表格的实现(进阶)
1.前言 在普通的可编辑表格的基础上,改进可编辑表格.数据来自外部的json(模拟服务端),通过json数据生成可编辑表格.根据实际情况,表格没有新增数据功能.表格的可编辑列,计算的列,每列的数据大小 ...
- Java 多线程写zip文件遇到的错误 write beyond end of stream!
最近在写一个大量小文件直接压缩到一个zip的需求,由于zip中的entry每一个都是独立的,不需要追加写入,也就是一个entry文件,写一个内容, 因此直接使用了多线程来处理,结果就翻车了,代码给出了 ...
- Java安全之CC3
前言 上一篇文章学习了Java中加载字节码的⼀些⽅法,其中介绍了TemplatesImpl,TemplatesImpl 是⼀个可以加载字节码的类,通过调⽤其newTransformer()⽅法,即可执 ...
- 关于C#Section配置未初始化的问题
转载 https://www.cnblogs.com/lxshwyan/p/10828305.html 如果使用了configSection节点,则configSection必须位于根节点的第0个.A ...