分类 技术 下的文章

结合 Python、Pygwalker、Pandas 和 Jupyter Notebook,为你的数据提供一个动态的可视化界面。

开源工具在推动技术进步和使其更加普及方面发挥了重要作用。数据分析也不例外。随着数据变得越来越丰富和复杂,数据科学家 始终在寻找简化工作流程并创建交互式和吸引人的可视化的方式。PyGWalker 就是为解决此类问题而设计的。

PyGWalker(Graphic Walker 的 Python 绑定)将 Python Jupyter Notebook 的工作环境连接到 Graphic Walker,以创建开源数据可视化工具。你可以通过简单的拖放操作将 Pandas 数据帧 转化为精美的数据可视化。

Exploring data through a visual interface with Pygwalker

开始使用 PyGWalker

使用 pip 安装 PyGWalker:

$ python3 -m pip install pygwalker

导入 pygwalkerpandas 以在项目中使用它:

import pandas as pd
import pygwalker as pyg

将数据加载到 Pandas 数据报中并调用 PyGWalker:

df = pd.read_csv('./bike_sharing_dc.csv', parse_dates=['date'])
gwalker = pyg.walk(df)

你现在有一个图形用户界面来探索和可视化你的 Pandas 数据帧!

使用 Graphic Walker 探索数据

Graphic Walker 的主要功能之一是能够更改标记类型以创建不同类型的图表。例如,通过将标记类型更改为折线来创建折线图。

Line charts generated by Pygwalker

你还可以通过创建 concat 视图来比较不同的度量,该视图将多个度量添加到行和列中。

Comparing data in the Graphic Walker interface.

将维度放入行或列中,以创建一个 facet 视图,这个视图包含多个子视图,这些子视图由一个维度中的值分隔开。

The facets view in Graphic Walker.

数据 Data 选项卡中,你可以在表格中查看数据帧并配置分析和语义类型。

Table data in Graphic Walker.

使用 PyGWalker 进行数据探索

你可以使用 PyGWalker 将 Pandas 数据转换为高度可定制的图形图表。你也可以使用 PyGWalker 作为探索数据的强大工具,以发现潜在的模式、趋势和洞察力。

数据探索选项可以在“ 探索模式 Exploration Mode ”选项(工具栏中)中找到。它们可以设置为点模式刷模式

  • 点模式:通过将你的鼠标光标指向数据的一个特定部分来探索数据。
  • 刷模式:通过在数据范围周围画一个选择框来探索数据,然后拖动选择框来查看生成的报告。

试试看你的数据

你可以在这些云演示中试用 PyGWalker:Google ColabBinderGraphic Walker Online Demo

PyGWalker 是一个用于简化数据分析和可视化工作流程的优秀工具,特别是对于那些想要使用 Pandas 进行界面可视化的人。借助 PyGWalker 和 Graphic Walker,数据科学家可以在 Jupyter Notebook 中通过简单的拖放操作轻松创建令人惊叹的可视化效果。请查看 PyGWalker Git 仓库获取源代码。

对于寻求自动化数据探索和高级增强分析的开源解决方案的数据科学家,该项目还适用于 RATH,这是一种开源自动 EDA、人工智能支持的数据探索和可视化工具。你还可以查看 RATH Git 仓库 获取源代码和活跃的社区。

(题图:MJ/21c21716-b900-4466-98a9-51268960c9b8)


via: https://opensource.com/article/23/4/data-visualization-pygwalker-jupyter-notebook

作者:Bill Wang 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

你是否正在寻找有关如何在 Linux 上安装 FreeIPA 服务器的简单指南?

此页面上的分步指南将展示如何在 RHEL 8、Rocky Linux 8 和 AlmaLinux 8 上安装 FreeIPA 服务器。

FreeIPA 是一个自由开源的基于 Linux 系统的集中式身份和访问管理工具,它是 Red Hat 身份管理器的上游项目。使用 FreeIPA,我们可以轻松地管理集中式身份验证以及帐户管理、策略(基于主机的访问控制)和审计。

FreeIPA 基于以下开源项目:

  • LDAP 服务器 – 基于 389 项目
  • KDC – 基于 MIT Kerberos 实现
  • 基于 Dogtag 项目的 PKI
  • 用于活动目录集成的 Samba 库
  • 基于 BIND 和 Bind-DynDB-LDAP 插件的 DNS 服务器
  • NTP

先决条件

  • 预装 RHEL 8 或 Rocky Linux 8 或 AlmaLinux 8
  • 具有管理员权限的 Sudo 用户
  • 内存 = 2 GB
  • CPU = 2 个 vCPU
  • 磁盘 = 根目录有 12GB 可用空间
  • 互联网连接

FreeIPA 的实验室详细信息

  • IP 地址 = 192.168.1.102
  • Hostanme = ipa.linuxtechi.lan
  • 操作系统:RHEL 8 或 Rocky Linux 8 或 AlmaLinux 8

事不宜迟,让我们深入了解 FreeIPA 安装步骤。

1、设置主机名并安装更新

打开服务器的终端并使用 hostnamectl 命令设置主机名:

$ sudo hostnamectl set-hostname "ipa.linuxtechi.lan"
$ exec bash

使用 yum/dnf 命令安装更新,然后重新启动:

$ sudo dnf update -y
$ sudo reboot

2、更新主机文件并将 SELinux 设置为许可

运行以下 tee 命令更新 /etc/hosts 文件,根据你的设置替换 IP 地址和主机名。

$ echo -e "192.168.1.102\tipa.linuxtechi.lan\t ipa" | sudo tee -a /etc/hosts

将 SELinux 设置为许可,运行以下命令:

$ sudo setenforce 0
$ sudo sed -i 's/^SELINUX=.*/SELINUX=permissive/g' /etc/selinux/config
$ getenforce
Permissive

3、安装 FreeIPA 及其组件

Appstream 包仓库中提供了 FreeIPA 包及其依赖项。由于我们计划安装集成 DNS 的 FreeIPA,因此我们还将安装 ipa-server-dnsbind-dyndb-ldap

运行以下命令安装 FreeIPA 及其依赖项:

$ sudo dnf -y install @idm:DL1
$ sudo dnf install freeipa-server ipa-server-dns bind-dyndb-ldap -y

4、开始安装 FreeIPA

成功安装 FreeIPA 包及其依赖项后,使用以下命令启动 FreeIPA 安装设置。

它将提示几件事,例如配置集成 DNS、主机名、域名和领域名。

$ sudo ipa-server-install

上述命令的输出如下所示:

在上面的窗口中输入 “yes” 后,需要一些时间来配置你的 FreeIPA 服务器,设置成功后,我们将得到下面的输出:

以上输出确认 FreeIPA 已成功安装。

5、在防火墙中允许 FreeIPA 端口

如果正在你的服务器上运行系统防火墙,那么运行如下 firewall-cmd 命令以允许 FreeIPA 端口:

$ sudo firewall-cmd --add-service={http,https,dns,ntp,freeipa-ldap,freeipa-ldaps} --permanent
$ sudo firewall-cmd --reload

6、访问 FreeIPA 管理门户

执行下面的 ipactl 命令查看 FreeIPA 的所有服务是否都在运行:

$ ipactl status
You must be root to run ipactl.
$ sudo ipactl status
Directory Service: RUNNING
krb5kdc Service: RUNNING
kadmin Service: RUNNING
named Service: RUNNING
httpd Service: RUNNING
ipa-custodia Service: RUNNING
pki-tomcatd Service: RUNNING
ipa-otpd Service: RUNNING
ipa-dnskeysyncd Service: RUNNING
ipa: INFO: The ipactl command was successful
$

让我们使用 kinit 命令验证管理员用户是否会通过 Kerberos 获取令牌,使用我们在 FreeIPA 安装期间提供的相同管理员用户密码。

$ kinit admin
$ klist

以上命令的输出:

完美,上面的输出确认管理员获得了令牌。现在,尝试访问 FreeIPA Web 控制台,在网络浏览器上输入以下 URL:

https://ipa.linuxtechi.lan/ipa/ui

或者

https://<Server-IPAddress>/ipa/ui

使用我们在安装过程中指定的用户名 admin 和密码。

对于 FreeIPA Web 控制台,使用自签名 SSL 证书,这就是我们看到此窗口的原因,因此单击“ 接受风险并继续 Accept the Risk and Continue ”。

输入凭据后,单击“ 登录 Log in ”。

这证实我们已在 RHEL 8/Rocky Linux 8 / AlmaLinux8 上成功设置 FreeIPA。

这就是全部,我希望你觉得它提供了很多信息。请在下面的评论部分中发表你的疑问和反馈。

(题图:MJ/9df57ea0-b5a0-48f9-a323-853a28ca6162)


via: https://www.linuxtechi.com/install-freeipa-rhel-rocky-almalinux/

作者:Pradeep Kumar 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Lens Desktop 是一个令人兴奋的 Kubernetes 工作平台。它是基于 OpenLens 资源库的一个定制化发行版本。通过本文来了解下 Lens Desktop 能做什么以及它是如何工作的。

Lens Desktop 是免费的。你可以查看 https://app.k8slens.dev/subscribe 来了解更多内容。Lens Desktop 有如下优势:

  • 简单高效 —— 你无需学习 kubectl 命令
  • 可视化已有的 Kubernetes 资源
  • 基于开源代码构建
  • 可观测性 —— 实时的统计数据、事件和日志流
  • 错误和警告可以直接在 Lens 仪表盘上看到
  • 支持 EKS、AKS、GKE、Minikube、Rancher、k0s、k3s、OpenShift
  • 强大的社区支持 —— 有 450000 用户,在 GitHub 上共获得 17000 星

Minikube 安装

Minikube 是一个用于本地运行 Kubernetes 的工具。它运行一个单节点的 Kubernetes 集群,这样就可以在 Kubernetes 上进行日常软件开发的实践工作。

我们将使用 Minikube 并验证 Lens 的用法。首先让我们在基于 Windows 的系统上安装 Minikube。你也可以把它安装在其他操作系统、虚拟机或笔记本电脑上。

  • 2 核以上 CPU
  • 2GB RAM
  • 20GB 空闲硬盘空间
  • 能连接网络
  • 容器或虚拟机管理器,如 Docker、VirtualBox

在终端或命令提示符处,运行 minikube start 命令:

minikube start --driver=virtualbox
* minikube v1.12.3 on Microsoft Windows 10 Home Single Language 10.0.19044 Build 19044
* Using the virtualbox driver based on existing profile
* minikube 1.26.0 is available! Download it: https://github.com/kubernetes/minikube/releases/tag/v1.26.0
* To disable this notice, run: ‘minikube config set WantUpdateNotification false’
* Starting control plane node minikube in cluster minikube
* virtualbox “minikube” VM is missing, will recreate.
* Creating virtualbox VM (CPUs=2, Memory=3000MB, Disk=20000MB) ...
! This VM is having trouble accessing https://k8s.gcr.io
* To pull new external images, you may need to configure a proxy: https://minikube.sigs.k8s.io/docs/reference/networking/proxy/
* Preparing Kubernetes v1.18.3 on Docker 19.03.12 ...
* Verifying Kubernetes components...
* Enabled addons: default-storageclass, storage-provisioner
* Done! kubectl is now configured to use “minikube”

进入你的 VirtualBox,并验证刚安装的 Minikube 虚拟机功能正常(图 1)。

Figure 1: Minikube virtual machine in virtual box

使用 minikube status 命令,查看状态是否与下面的输出一致:

C:\>minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

然后,使用 kubectl cluster-info 命令查看 KubeDNS 详情:

kubectl cluster-info
Kubernetes master is running at https://192.168.99.103:8443
KubeDNS is running at https://192.168.99.103:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

你可以使用 kubectl cluster-info dump 命令来调试和诊断集群问题。

当 Minikube 安装完成后,安装 kubectlhttps://kubernetes.io/docs/tasks/tools/)。它是一个命令行集群,用于对 Kubernetes 集群和 Minikube 执行命令。

Figure 2: Lens

执行 kubectl get nodes 命令获取所有 节点 node 的详情,在本例中是获取 Minikube 的详情:

C:\>kubectl get nodes
NAME       STATUS   ROLES    AGE     VERSION
minikube   Ready    master   7m57s   v1.18.3

使用 kubectl get all 命令获取默认命名空间下的所有详情:

C:\>kubectl get all
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   7m58s

我们现在已经有一个 Minikube 集群,并准备好了 Kubectl。下一步是安装和配置 Lens,并用示例应用程序来验证。

Lens 的安装和配置

打开 https://k8slens.dev/ ,下载与你的操作系统匹配的安装包。

然后,参照屏幕上的教程来安装 Lens,安装完成后打开 Lens。你会发现在目录中有一个 minikube(图 3)。

Figure 3: Lens catalogue

点击 “minikube” 后,你就进入了 Minikube 的世界,你会爱上它的。

点击 节点 node 获取有关 kubectl get nodes 命令输出的 节点 node 详情。

现在,你可以使用 Lens 了。

Figure 4: Lens cluster

我们现在部署 https://github.com/GoogleCloudPlatform/microservices-demo,这是一个云原生微服务演示应用程序。它有 11 层的微服务应用,是一个基于网络的电子商务应用。

下载这个应用程序,把它解压到与 Minikube 相同的目录。

进入 release 目录,执行以下命令。

kubectl apply -f kubernetes-manifests.yaml

deployment.apps/emailservice created
service/emailservice created
deployment.apps/checkoutservice created
service/checkoutservice created
deployment.apps/recommendationservice created
service/recommendationservice created
deployment.apps/frontend created
service/frontend created
service/frontend-external created
deployment.apps/paymentservice created
service/paymentservice created
deployment.apps/productcatalogservice created
service/productcatalogservice created
deployment.apps/cartservice created
service/cartservice created
deployment.apps/loadgenerator created
deployment.apps/currencyservice created
service/currencyservice created
deployment.apps/shippingservice created
service/shippingservice created
deployment.apps/redis-cart created
service/redis-cart created
deployment.apps/adservice created
service/adservice created

安装过程现在应该已经开始了,不过它需要一些时间来反映出我们使用了 kubectl 命令。

Figure 5: Lens nodes

kubectl get pods
NAME                 READY   STATUS    RESTARTS   AGE
adservice-775d8b9bf5-cp7jr   0/1     Pending   0          8h
cartservice-79749895f5-jrq4d  1/1     Running   0         8h
checkoutservice-5645bf9c65-882m4  1/1   Running  0        8h
currencyservice-545c79d477-8rhg7  1/1  Running   0         8h
emailservice-7cc5c74b4f-hk74s     1/1  Running   0        8h
frontend-9cdf787f5-klfkh    1/1     Running   1          8h
loadgenerator-7b6874cb4c-645v9   1/1  Running   0        8h
paymentservice-5f74bc7b87-l4248  1/1  Running   0        8h
productcatalogservice-6846f59899-v4q4w  1/1  Running  0  8h
recommendationservice-d9c6c8b55-m2x9k  1/1  Running   0  8h
redis-cart-57bd646894-v7kfr    0/1   Pending   0         8h
shippingservice-8685dd9855-pmgjm  1/1  Running  0        8h

表 1 列出了你可以通过 kubectl 来获取信息的几个命令。

Figure 6: Lens pods

描述命令
列出节点kubectl get node
列出集群中的所有资源kubectl get all –all-namespaces
列出部署kubectl get deployment
显示部署的完整状态kubectl describe deployment <deployment_name>
修改集群上的部署kubectl edit deployment <deployment_name>
删除部署kubectl delete deployment <deployment_name>
列出容器荚kubectl get pod
删除容器荚kubectl delete pod <pod_name>
显示容器荚的完整状态kubectl describe pod <pod_name>
在 Shell 中运行一个单容器荚kubectl exec -it <pod_name> /bin/bash
列出机密信息kubectl get secrets
列出服务kubectl get services
列出服务的完整状态kubectl describe services
修改集群中的服务kubectl edit services / kubectl edit deployment <deployment_name>
列出命名空间kubectl get namespace <namespace_name>
打印容器荚日志kubectl logs <pod_name>
打印容器荚中特定容器的日志kubectl logs -c <container_name> <pod_name>

Lens 不仅可以帮你获取表 1 中列出的所有信息,它还可以获取指定集群的信息。我们还能用 Lens 来对 Kubernetes 资源进行编辑和删除操作。

Figure 7: Lens deployments

我们来看下是如何操作的。在 工作负载 Workloads 部分选择 容器荚 Pod (图 6),我们能通过 Lens 来编辑、删除、查看日志、访问 容器荚 Pod 的终端,这是不是很酷?

Figure 8: Lens Replicasets

你可以验证 工作负载 Workloads 区域中所有 部署 deployments (图 7), 工作负载 Workloads 区域中所有 副本 Replicasets (图 8), 配置 Config 区域中所有 密钥 Secrets (图 9),以及 网络 Network 区域中所有 服务 Services 是否都正常(图 10),

Figure 9: Lens Secrets

你可以看到,跳转到所有的资源以及在一个地方高效地查看所有资源就是如此轻松。我们可以用 Lens 修改 YAML 文件,在运行时应用它来查看变更。

Figure 10: Lens Services

对于配置在不同的云服务商部署的多个集群,我们仍可以用 Lens 来进行观察和故障处理。

(题图:MJ/069da8c5-9043-46b3-9b14-87a0ffc6bb35)


via: https://www.opensourceforu.com/2022/09/monitoring-and-debugging-kubernetes-with-lens-desktop/

作者:Mitesh Soni 选题:lkxed 译者:lxbwolf 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这篇关于 MySQL 中日期和时间的概述将帮助你在数据库表中处理时间值。

流行数据库系统 MySQL 的新老用户常常会对数据库处理时间值的方式感到困惑。有时用户不会费心去了解时间值的数据类型。这可能是因为他们觉得本身也没有什么好了解的。日期就是日期,对吧?好吧,并非总是如此。花几分钟时间了解 MySQL 如何存储和显示日期和时间是有益的。学习如何最好地利用数据库表中的时间值可以帮助你成为更好的编码者。

MySQL 时间值类型

当你在 MySQL 中新建表时,选择合适的数据类型(INTFLOATCHAR 等)高效地保存插入到表中的数据。MySQL 为时间值提供了五种数据类型。它们是 DATETIMEDATETIMETIMESTAMPYEAR

MySQL 使用 ISO 8601 格式来存储以下格式的值(LCTT 译注:国际标准 ISO 8601,是国际标准化组织的日期和时间的表示方法,全称为《数据存储和交换形式·信息交换·日期和时间的表示方法》):

  • DATEYYYY-MM-DD
  • TIMEHH:MM:SS
  • TIMESTAMPYYYY-MM-DD HH:MM:SS
  • YEARYYYY

DATETIME 与 TIMESTAMP 的比较

你可能已经注意到 日期时间 DATETIME 时间戳 TIMESTAMP 数据类型存有相同的数据。你可能想知道这两者之间是否有差异。答案是:有。

首先,可以使用的日期范围不同。DATETIME 可以保存 1000-01-01 00:00:00 和 9999-12-31 23:59:59 之间的日期,而 TIMESTAMP 的范围更有限,从 1970-01-01 00:00:01 到 2038-01-19 03:14:07 UTC。

其次,虽然两种数据类型都允许你 自动初始化 auto_initialize 自动更新 auto_update 它们各自的值(分别用 DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP),但在 5.6.5 版本之前,对 DATETIME 值不能这样操作。如果你要用 DATETIME,你可以使用 CURRENT_TIMESTAMP 的 MySQL 同义词之一,例如 NOW()LOCALTIME()

如果你对一个 DATETIME 值使用 ON UPDATE CURENT_TIMESTAMP(或其同义词之一),但没有使用 DEFAULT CURRENT_TIMESTAMP 子句,那么这个列的默认值为 NULL。除非你在表的定义中包含 NOT NULL,在这种情况下,它默认为 0。

另一件需要记住的重要事情是,尽管通常情况下,除非你声明一个默认值,否则 DATETIMETIMESTAMP 列都没有一个默认值,但这个规则有一个例外。如果没有指定 DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP 这两个子句,并且禁用 explicit_defaults_for_timestamp 这个变量,那么你表中的第一个 TIMESTAMP 列将被隐式创建。

要检查这个变量的状态,请运行:

mysql> show variables like 'explicit_default%';

如果你想打开或关闭它,运行这段代码(用 0 表示关闭,用 1 表示打开):

mysql> set explicit_defaults_for_timestamp = 0;

TIME

MySQL 的 时间 TIME 数据类型可能看起来很简单,但有几件事是一个优秀的程序员应该牢记的。

首先要注意的是,虽然 TIME 经常被认为是一天中的时间,但它实际上是经过的时间。换句话说,它可以是一个负值,或者可以大于 23:59:59。在 MySQL 中,一个 TIME 值的范围可以是 -838:59:59 到 838:59:59。

另外,如果你缩写一个时间值,MySQL 会因你是否使用冒号作出不同解释。例如,10:34 这个值被 MySQL 看作是 10:34:00。也就是说,十点过后的 34 分钟。但是,如果你不使用冒号写作 1034,MySQL 将其视为 00:10:34,意思是 10 分钟 34 秒。

最后,你应该知道 TIME 值(以及 DATETIMETIMESTAMP 字段的时间部分)从 5.6.4 版本开始,可以取一个小数部分。要使用它,请在数据类型定义的结尾处添加一个整数(最大值为 6)的圆括号。

time_column TIME(2)

时区

时区变化不仅在现实世界中产生混乱和疲劳,而且也会在数据库系统中制造麻烦。地球被划分为 24 个独立的时区,通常每隔 15 度经度就会发生变化。我说通常是因为一些国家行事方式不同。例如中国只在一个时区运作,而不是预期的五个时区。

你如何处理处于不同时区的数据库系统的用户就成了一个问题。幸运的是,MySQL 并没有使这个问题变得太困难。

要检查你的会话时区,请运行:

mysql> select @@session.time_zone;

如果结果显示 System,这意味着它正在使用你的 my.cnf 配置文件中设置的时区。如果你在本地计算机上运行你的 MySQL 服务器,这可能就是你会得到的,你不需要做任何改变。

如果你想改变你的会话的时区,请运行如下命令:

mysql> set time_zone = '-05:00';

这将你的时区设置为 美国/东部 US/Eastern ,比 协调世界时 UTC 晚五个小时。

获得一周的日期

为了跟上本教程后面部分的代码,你应该在你的系统中创建一个带有日期值类型的表。比如:

mysql> create table test
( row_id smallint not null auto_increment primary key,
the_date date not null);

然后使用 ISO 8601 格式在表中插入一些随机日期,如

mysql> insert into test (the_date) VALUES ('2022-01-05');

我在我的 test 表中插入了四行日期值,你插入多少行都可以。

有时你可能想知道某一天是星期几。MySQL 给了你几种实现方法。

第一种,也是最显而易见的方法,是使用 DAYNAME() 函数。如下示例表所展示,DAYNAME() 函数可以告诉你每个日期是星期几:

mysql> SELECT the_date, DAYNAME(the_date) FROM test;
+------------+-------------------------------+
| the_date   | DAYNAME(the_date)             |
+------------+-------------------------------+
| 2021-11-02 | Tuesday                       |
| 2022-01-05 | Wednesday                     |
| 2022-05-03 | Tuesday                       |
| 2023-01-13 | Friday                        |
+------------+-------------------------------+
4 rows in set (0.00 sec)

另外两种获取星期几的方法是返回整数值,而不是星期几的名称,分别是 WEEKDAY()DAYOFWEEK()。他们都返回数字,却又各不相同。WEEKDAY() 函数返回从 0 到 6 的数字,其中 0 代表星期一,6 代表星期日。而 DAYOFWEEK() 则返回从 1 到 7 的数字,其中 1 代表星期日,7 代表星期六。

mysql> SELECT the_date, DAYNAME(the_date),
WEEKDAY(the_date), DAYOFWEEK(the_date) FROM test;
+------------+------------------+------------------+--------------------+
| the_date   | DAYNAME(the_date)| WEEKDAY(the_date)| DAYOFWEEK(the_date)|
| 2021-11-02 | Tuesday          | 1                | 3                  |
| 2022-01-05 | Wednesday        | 2                | 4                  |
| 2022-05-03 | Tuesday          | 1                | 3                  |
| 2023-01-13 | Friday           | 4                | 6                  |
+------------+------------------+------------------+--------------------+
4 rows in set (0.00 sec)

当你只想获取日期的一部分时

有时你可能在 MySQL 表中存储了一个日期,但是你只想获取日期的一部分。这并不是问题。

MySQL 中有几个顾名思义的函数,可以轻松获取日期对象的特定部分。以下是一些示例:

mysql> SELECT the_date, YEAR(the_date), MONTHNAME(the_date), 
DAYOFMONTH(the_date) FROM test ;
+-----------+---------------+-------------------+---------------------+
| the_date  | YEAR(the_date)|MONTHNAME(the_date)| DAYOFMONTH(the_date)|
+-----------+---------------+-------------------+---------------------+
| 2021-11-02| 2021          | November          | 2                   |
| 2022-01-05| 2022          | January           | 5                   |
| 2022-05-03| 2022          | May               | 3                   |
| 2023-01-13| 2023          | January           | 13                  |
+-----------+---------------+-------------------+---------------------+
4 rows in set (0.00 sec)

MySQL 也允许你使用 EXTRACT() 函数来获取日期的一部分。你提供给函数的参数是一个单位说明符(确保是单数形式)、FROM 和列名。因此,为了从我们的 test 表中仅获取年份,你可以写:

mysql> SELECT EXTRACT(YEAR FROM the_date) FROM test;
+----------------------------------------------+
| EXTRACT(YEAR FROM the_date)                  |
+----------------------------------------------+
| 2021                                         |
| 2022                                         |
| 2022                                         |
| 2023                                         |
+----------------------------------------------+
4 rows in set (0.01 sec)

插入和读取不同格式的日期

正如之前提到的,MySQL 使用 ISO 8601 格式存储日期和时间值。但是如果你想以另一种方式存储日期和时间值,例如 MM-DD-YYYY 格式,怎么办?首先,不要尝试这样做。MySQL 以 8601 格式存储日期和时间,就是这样。不要尝试更改它。但是,这并不意味着你必须在将数据输入到数据库之前将数据转换为特定的格式,或者你不能以任何你想要的格式展示数据。

如果你想要将非 ISO 的格式的日期输入到表中,你可以使用 STR_TO_DATE() 函数。第一个参数是你想要存储在数据库中的日期的字符串值。第二个参数是格式化字符串,它让 MySQL 知道日期的组织方式。让我们看一个简单的例子,然后我将更深入地研究这个看起来很奇怪的格式化字符串是什么。

mysql> insert into test (the_date) values (str_to_date('January 13, 2023','%M %d, %Y'));

Query OK, 1 row affected (0.00 sec)

你将格式化字符串放在引号中,并在每个特殊字符前加上百分号。上面代码中的格式序列告诉 MySQL 我的日期由一个完整的月份名称 %M,后跟一个两位数的日期%d,然后是一个逗号,最后由一个四位数的年份 %Y 组成。请注意,大写很重要。

一些其他常用的格式化字符串字符是:

  • %b 缩写月份的名称(例如: Jan
  • %c 数字月份(例如: 1)
  • %W 星期名称(例如: `Saturday)
  • %a 星期名称的缩写(例如: Sat
  • %T 24 小时制的时间(例如: 22:01:22
  • %r 带 AM/PM 的 12 小时制的时间(例如: 10:01:22 PM
  • %y 两位数的年份(例如: 23)

请注意,对于两位数年份 %y,年份范围是 1970 到 2069。因此,从 70 到 99 的数字被假定为 20 世纪,而从 00 到 69 的数字被假定为 21 世纪。

如果你有一个日期存储在你的数据库中,你想用不同的格式显示它,你可以使用这个 DATE_FORMAT() 函数:

mysql> SELECT DATE_FORMAT(the_date, '%W, %b. %d, %y') FROM test;
+-----------------------------------------+
| DATE_FORMAT(the_date, '%W, %b. %d, %y') |
+-----------------------------------------+
| Tuesday, Nov. 02, 21                    |
| Wednesday, Jan. 05, 22                  |
| Tuesday, May. 03, 22                    |
| Friday, Jan. 13, 23                     |
+-----------------------------------------+
4 rows in set (0.00 sec)

总结

本教程应该为你提供了一个关于 MySQL 中的日期和时间值的有用的概述。我希望本文教会了您一些新知识,使您能够更好地控制和理解 MySQL 数据库如何处理时间值。

(题图:MJ/76b6481a-a271-4e81-bc17-dd7fbe08a240)


via: https://opensource.com/article/23/2/temporal-values-mysql

作者:Hunter Coleman 选题:lkxed 译者:hanszhao80 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

推进你的 Rust 学习,熟悉 Rust 程序的变量和常量。

该系列的第一章中,我讲述了为什么 Rust 是一门越来越流行的编程语言。我还展示了如何 在 Rust 中编写 Hello World 程序

让我们继续 Rust 之旅。在本文中,我将向你介绍 Rust 编程语言中的变量和常量。

此外,我还将讲解一个称为“ 遮蔽 shadowing ”的新编程概念。

Rust 变量的独特之处

在编程语言中,变量是指 存储某些数据的内存地址的一个别名

对 Rust 语言来讲也是如此。但是 Rust 有一个独特的“特性”。每个你声明的变量都是 默认 不可变的 immutable 。这意味着一旦给变量赋值,就不能再改变它的值。

这个决定是为了确保默认情况下,你不需要使用 自旋锁 spin lock 互斥锁 mutex 等特殊机制来引入多线程。Rust 会保证 安全的并发。由于所有变量(默认情况下)都是不可变的,因此你不需要担心线程会无意中更改变量值。

这并不是在说 Rust 中的变量就像常量一样,因为它们确实不是常量。变量可以被显式地定义为可变的。这样的变量称为 可变变量

这是在 Rust 中声明变量的语法:

// 默认情况下不可变
// 初始化值是**唯一**的值
let variable_name = value;

// 使用 'mut' 关键字定义可变变量
// 初始化值可以被改变
let mut variable_name = value;

? 尽管你可以改变可变变量的值,但你不能将另一种数据类型的值赋值给它。

这意味着,如果你有一个可变的浮点型变量,你不能在后面将一个字符赋值给它。

Rust 数据类型概观

在上一篇文章中,你可能注意到了我提到 Rust 是一种强类型语言。但是在定义变量时,你不需要指定数据类型,而是使用一个通用的关键字 let

Rust 编译器可以根据赋值给变量的值推断出变量的数据类型。但是如果你仍然希望明确指定数据类型并希望注释类型,那么可以这样做。以下是语法:

let variable_name: data_type = value;

下面是 Rust 编程语言中一些常见的数据类型:

  • 整数类型:分别用于有符号和无符号的 32 位整数的 i32u32
  • 浮点类型:分别用于 32 位和 64 位浮点数的 f32f64
  • 布尔类型bool
  • 字符类型char

我会在下一篇文章中更详细地介绍 Rust 的数据类型。现在,这应该足够了。

? Rust 并不支持隐式类型转换。因此,如果你将值 8 赋给一个浮点型变量,你将会遇到编译时错误。你应该赋的值是 8.8.0

Rust 还强制要求在读取存储在其中的值之前初始化变量。

{ // 该代码块不会被编译
    let a;
    println!("{}", a); // 本行报错
    // 读取一个**未初始化**变量的值是一个编译时错误
}

{ // 该代码块会被编译
    let a;
    a = 128;
    println!("{}", a); // 本行不会报错
    // 变量 'a' 有一个初始值
}

如果你在不初始化的情况下声明一个变量,并在给它赋值之前使用它,Rust 编译器将会抛出一个 编译时错误

虽然错误很烦人,但在这种情况下,Rust 编译器强制你不要犯写代码时常见的错误之一:未初始化的变量。

Rust 编译器的错误信息

来写几个程序,你将

  • 通过执行“正常”的任务来理解 Rust 的设计,这些任务实际上是内存相关问题的主要原因
  • 阅读和理解 Rust 编译器的错误/警告信息

测试变量的不可变性

让我们故意写一个试图修改不可变变量的程序,看看接下来会发生什么。

fn main() {
    let mut a = 172;
    let b = 273;
    println!("a: {a}, b: {b}");

    a = 380;
    b = 420;
    println!("a: {}, b: {}", a, b);
}

直到第 4 行看起来都是一个简单的程序。但是在第 7 行,变量 b —— 一个不可变变量 —— 的值被修改了。

注意打印 Rust 变量值的两种方法。在第 4 行,我将变量括在花括号中,以便打印它们的值。在第 8 行,我保持括号为空,并使用 C 的风格将变量作为参数。这两种方法都是有效的。(除了修改不可变变量的值,这个程序中的所有内容都是正确的。)

来编译一下!如果你按照上一章的步骤做了,你已经知道该怎么做了。

$ rustc main.rs
error[E0384]: cannot assign twice to immutable variable `b`
 --> main.rs:7:5
  |
3 |     let b = 273;
  |         -
  |         |
  |         first assignment to `b`
  |         help: consider making this binding mutable: `mut b`
...
7 |     b = 420;
  |     ^^^^^^^ cannot assign twice to immutable variable

error: aborting due to previous error

For more information about this error, try `rustc --explain E0384`.
? “binding” 一词是指变量名。但这只是一个简单的解释。

这很好的展示了 Rust 强大的错误检查和信息丰富的错误信息。第一行展示了阻止上述代码编译的错误信息:

error[E0384]: cannot assign twice to immutable variable b

这意味着,Rust 编译器注意到我试图给变量 b 重新赋值,但变量 b 是一个不可变变量。所以这就是导致这个错误的原因。

编译器甚至可以识别出错误发生的确切行和列号。

在显示 first assignment to b 的行下面,是提供帮助的行。因为我正在改变不可变变量 b 的值,所以我被告知使用 mut 关键字将变量 b 声明为可变变量。

?️ 自己实现一个修复来更好地理解手头的问题。

使用未初始化的变量

现在,让我们看看当我们尝试读取未初始化变量的值时,Rust 编译器会做什么。

fn main() {
    let a: i32;
    a = 123;
    println!("a: {a}");

    let b: i32;
    println!("b: {b}");
    b = 123;
}

这里,我有两个不可变变量 ab,在声明时都没有初始化。变量 a 在其值被读取之前被赋予了一个值。但是变量 b 的值在被赋予初始值之前被读取了。

来编译一下,看看结果。

$ rustc main.rs
warning: value assigned to `b` is never read
 --> main.rs:8:5
  |
8 |     b = 123;
  |     ^
  |
  = help: maybe it is overwritten before being read?
  = note: `#[warn(unused_assignments)]` on by default

error[E0381]: used binding `b` is possibly-uninitialized
 --> main.rs:7:19
  |
6 |     let b: i32;
  |         - binding declared here but left uninitialized
7 |     println!("b: {b}");
  |                   ^ `b` used here but it is possibly-uninitialized
  |
  = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0381`.

这里,Rust 编译器抛出了一个编译时错误和一个警告。警告说变量 b 的值从来没有被读取过。

但是这是荒谬的!变量 b 的值在第 7 行被访问了。但是仔细看;警告是关于第 8 行的。这很令人困惑;让我们暂时跳过这个警告,继续看错误。

这个错误信息说 used binding b is possibly-uninitialized。和之前的例子一样,Rust 编译器指出错误是由于尝试在第 7 行读取变量 b 的值而引起的。读取变量 b 的值是错误的原因是它的值没有初始化。在 Rust 编程语言中,这是非法的。因此编译时错误出现。

?️ 这个错误可以很容易地通过交换第 7 和第 8 行的代码来解决。试一下,看看错误是否消失了。

示例程序:交换数字

现在你已经熟悉了常见的变量相关问题,让我们来看一个交换两个变量值的程序。

fn main() {
    let mut a = 7186932;
    let mut b = 1276561;

    println!("a: {a}, b: {b}");

    // 交换变量值
    let temp = a;
    a = b;
    b = temp;

    println!("a: {}, b: {}", a, b);
}

我在这里声明了两个变量 ab。这两个变量都是可变的,因为我希望在后面改变它们的值。我赋予了一些随机值。最初,我打印了这些变量的值。

然后,在第 8 行,我创建了一个名为 temp 的不可变变量,并将存储在 a 中的值赋给它。之所以这个变量是不可变的,是因为 temp 的值不会改变。

要交换值,我将变量 b 的值赋给变量 a,在下一行,我将 temp 的值(它包含 a 的值)赋给变量 b。现在值已经交换了,我打印了变量 ab 的值。

在编译并执行上面的代码后,我得到了以下输出:

a: 7186932, b: 1276561
a: 1276561, b: 7186932

正如你所见,值已经交换了。完美。

使用未使用的变量

当你声明了一些变量,打算在后面使用它们,但是还没有使用它们,然后编译你的 Rust 代码来检查一些东西时,Rust 编译器会警告你。

原因是显而易见的。不会被使用的变量占用了不必要的初始化时间(CPU 周期)和内存空间。如果不会被使用,为什么要在程序写上它呢?尽管编译器确实会优化这一点。但是它仍然是一个问题,因为它会以多余的代码的形式影响可读性。

但是,有的时候,你可能会面对这样的情况:创建一个变量与否不在你的控制之下。比如说,当一个函数返回多个值,而你只需要其中的一些值时。在这种情况下,你不能要求库维护者根据你的需要调整他们的函数。

所以,在这种情况下,你可以写一个以下划线开头的变量,Rust 编译器将不再显示这样的警告。如果你真的不需要使用存储在该未使用变量中的值,你可以简单地将其命名为 _(下划线),Rust 编译器也会忽略它!

接下来的程序不仅不会生成任何输出,而且也不会生成任何警告和/或错误消息:

fn main() {
    let _unnecessary_var = 0; // 没有警告
    let _ = 0.0; // 完全忽略
}

算术运算

数学就是数学,Rust 并没有在这方面创新。你可以使用在其他编程语言(如 C、C++ 和/或 Java)中使用过的所有算术运算符。

包含可以在 Rust 编程语言中使用的所有运算符和它们的含义的完整列表可以在 这里 找到。

示例程序:一个生锈的温度计

(LCTT 译注:这里的温度计“生锈”了是因为它是使用 Rust(生锈)编写的,原作者在这里玩了一个双关。)

接下来是一个典型的程序,它将华氏度转换为摄氏度,反之亦然。

fn main() {
    let boiling_water_f: f64 = 212.0;
    let frozen_water_c: f64 = 0.0;

    let boiling_water_c = (boiling_water_f - 32.0) * (5.0 / 9.0);
    let frozen_water_f = (frozen_water_c * (9.0 / 5.0)) + 32.0;

    println!(
        "Water starts boiling at {}°C (or {}°F).",
        boiling_water_c, boiling_water_f
    );
    println!(
        "Water starts freezing at {}°C (or {}°F).",
        frozen_water_c, frozen_water_f
    );
}

没什么大不了的……华氏温度转换为摄氏温度,反之亦然。

正如你在这里看到的,由于 Rust 不允许自动类型转换,我不得不在整数 32、9 和 5 后放一个小数点。除此之外,这与你在 C、C++ 和/或 Java 中所做的类似。

作为练习,尝试编写一个程序,找出给定数中有多少位数字。

常量

如果你有一些编程知识,你可能知道这意味着什么。常量是一种特殊类型的变量,它的值永远不会改变它保持不变

在 Rust 编程语言中,使用以下语法声明常量:

const CONSTANT_NAME: data_type = value;

如你所见,声明常量的语法与我们在 Rust 中看到的变量声明非常相似。但是有两个不同之处:

  • 常量的名字需要像 SCREAMING_SNAKE_CASE 这样。所有的大写字母和单词之间用下划线分隔。
  • 常量的数据类型必须被显性定义。

变量与常量的对比

你可能在想,既然变量默认是不可变的,为什么语言还要包含常量呢?

接下来这个表格应该可以帮助你消除疑虑。(如果你好奇并且想更好地理解这些区别,你可以看看我的博客,它详细地展示了这些区别。)

一个展示 Rust 编程语言中变量和常量之间区别的表格

使用常量的示例程序:计算圆的面积

这是一个很直接的关于 Rust 中常量的简单程序。它计算圆的面积和周长。

fn main() {
    const PI: f64 = 3.14;
    let radius: f64 = 50.0;

    let circle_area = PI * (radius * radius);
    let circle_perimeter = 2.0 * PI * radius;

    println!("有一个周长为 {radius} 厘米的圆");
    println!("它的面积是 {} 平方厘米", circle_area);
    println!(
        "以及它的周长是 {} 厘米",
        circle_perimeter
    );
}

如果运行代码,将产生以下输出:

有一个周长为 50 厘米的圆
它的面积是 7850 平方厘米
以及它的周长是 314 厘米

Rust 中的变量遮蔽

如果你是一个 C++ 程序员,你可能已经知道我在说什么了。当程序员声明一个与已经声明的变量同名的新变量时,这就是变量遮蔽。

与 C++ 不同,Rust 允许你在同一作用域中执行变量遮蔽!

? 当程序员遮蔽一个已经存在的变量时,新变量会被分配一个新的内存地址,但是使用与现有变量相同的名称引用。

来看看它在 Rust 中是如何工作的。

fn main() {
    let a = 108;
    println!("a 的地址: {:p}, a 的值 {a}", &a);
    let a = 56;
    println!("a 的地址: {:p}, a 的值: {a} // 遮蔽后", &a);

    let mut b = 82;
    println!("\nb 的地址: {:p}, b 的值: {b}", &b);
    let mut b = 120;
    println!("b的地址: {:p}, b的值: {b} // 遮蔽后", &b);

    let mut c = 18;
    println!("\nc 的地址: {:p}, c的值: {c}", &c);
    c = 29;
    println!("c 的地址: {:p}, c的值: {c} // 遮蔽后", &c);
}

println 语句中花括号内的 :p 与 C 中的 %p 类似。它指定值的格式为内存地址(指针)。

我在这里使用了 3 个变量。变量 a 是不可变的,并且在第 4 行被遮蔽。变量 b 是可变的,并且在第 9 行也被遮蔽。变量 c 是可变的,但是在第 14 行,只有它的值被改变了。它没有被遮蔽。

现在,让我们看看输出。

a 的地址: 0x7ffe954bf614, a 的值 108
a 的地址: 0x7ffe954bf674, a 的值: 56 // 遮蔽后

b 的地址: 0x7ffe954bf6d4, b 的值: 82
b 的地址: 0x7ffe954bf734, b 的值: 120 // 遮蔽后

c 的地址: 0x7ffe954bf734, c 的值: 18
c 的地址: 0x7ffe954bf734, c 的值: 29 // 遮蔽后

来看看输出,你会发现不仅所有三个变量的值都改变了,而且被遮蔽的变量的地址也不同(检查十六进制的最后几个字符)。

变量 ab 的内存地址改变了。这意味着变量的可变性或不可变性并不是遮蔽变量的限制。

总结

本文介绍了 Rust 编程语言中的变量和常量。还介绍了算术运算。

做个总结:

  • Rust 中的变量默认是不可变的,但是可以引入可变性。
  • 程序员需要显式地指定变量的可变性。
  • 常量总是不可变的,无论如何都需要类型注释。
  • 变量遮蔽是指使用与现有变量相同的名称声明一个 变量。

很好!我相信和 Rust 一起的进展不错。在下一章中,我将讨论 Rust 中的数据类型。敬请关注。

与此同时,如果你有任何问题,请告诉我。

(题图:MJ/7c5366b8-f926-487e-9153-0a877145ca5)


via: https://itsfoss.com/rust-variables/

作者:Pratham Patel 选题:lkxed 译者:Cubik 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

使用这些 Drupal 模块,使你的网站对每个人都可以无障碍访问。

随着网站的 无障碍访问 accessibility 继续成为人们日益关注的问题,网站所有者和开发人员需要确保他们的网站符合美国残疾人法案(ADA)。Drupal 是一种流行的开源内容管理系统(CMS),它提供各种工具和模块以确保所有用户都可以访问你的网站,而无论他们的能力如何。本文讨论了网站无障碍访问的重要性、ADA 合规性的基本要求,以及 Drupal 如何帮助你实现合规性。

为什么网站无障碍访问很重要

出于多种原因,网站无障碍访问很重要。首先,它确保残障人士可以访问和使用你的网站。这包括有视觉、听觉、身体和认知障碍的人。通过使你的网站可以无障碍访问,你不仅遵守了法律,而且还为所有用户提供了更好的体验。

此外,网站无障碍访问可以改善你网站的搜索引擎优化(SEO)并提高网站的可用性。搜索引擎优先考虑无障碍的网站,如果易于使用,用户更有可能在你的网站上停留更长时间并与你互动。

ADA 合规性的基本要求

ADA 要求所有网站和数字内容都可供残障人士访问。ADA 合规性的一些基本要求包括:

  • 为所有图像和非文本内容提供替代文本描述。
  • 确保所有视频都有字幕和文字说明。
  • 使用颜色对比和其他设计元素使你的网站更具可读性。
  • 提供访问内容的替代方式,例如音频描述和键盘导航。
  • 确保你的网站与辅助技术兼容,例如屏幕阅读器和盲文显示器。

Drupal 如何帮助你实现合规性

Drupal 提供各种工具和模块来帮助你实现网站的无障碍和 ADA 合规性。以下是我认为最有用的七个:

总结

出于法律原因和为所有用户提供更好的用户体验,确保网站无障碍访问和 ADA 合规性非常重要。从无障碍访问检查器到颜色对比分析器,Drupal 提供了多种方法来确保你的网站符合 ADA 标准。使用 Drupal 的工具和模块,你可以让每个人都可以访问你的网站,无论他们的能力如何,并提供更好的用户体验。


via: https://opensource.com/article/23/4/drupal-modules-website-accessibility

作者:Neeraj Kumar 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出