编辑2:
问题:
Linux 中通过 USB 从 Android 复制的文件显示的文件修改时间stat
受到创建文件后更改 Android 上的时区设置的影响。
重新表现:
- 从 live USB 启动 Ubuntu 20.4(或 Linux Mint 21)。
- 在Android上(我有版本11,也观察了9的效果)将日期时间和时区设置为手动,置于离线模式。
- 通过 USB 将 Android 连接到 Linux。
- 在 Android 上选择一个文件,通过文件管理器复制到 Linux 上的 location_1。
stat
在复制的文件(location_1 中的一个)上运行。- 断开 USB 连接(重要)。
- 将 Android 上的时区更改几个小时。
- 重新连接 USB。
- 将同一文件从 Android 复制到 location_2。
stat
在复制的文件(location_2 中的一个)上运行。- 在线观察
Modify
几个小时的差异。
操作:
2013年有人问过一个问题如何通过 USB 在 Android 和 Linux 之间传输文件?。 2018 年更新的答案指出 mtp 有效:
看来大多数 Linux 发行版现在都可以很好地使用 MTP。根据我的经验,Mint(基于 Ubuntu)开箱即用
事实上,我通过 USB 连接设备,单击 Nemo (GUI) 图标,安装存储,然后我可以在 GUI 中传输文件。
不过我刚刚注意到时区很重要。当我更改手机上的时区时,文件修改时间会更改。复制到 Linux 后,stat
无论设备的时区如何,它们都会保留这些时间和 Linux 时区(按 ),因此文件的“原始”(手机)时区校正信息就会丢失。在我看来,这不是理想的效果,尽管很少表现出来,因为通常物理上接近的设备都设置了相同的时区。
这种影响是由于mtp
工作方式造成的还是可能取决于其他因素?有什么建议如何以正确的时间进行复制而不确保两个设备在复制文件时设置相同的时区? TIA
PS 我想我想报告一个错误,但不确定在哪里:Mint、Ubuntu、Debian、内核,还有其他吗?
添加的示例:
Android 上的文件时区 +1,Linux 时区 +1
在 Nemo 中基于 Linux Mint 21 的系统中的 Android 文件管理器和 mtp 挂载中可以看到 Android 修改时间,例如:9:45:00。
复制到 ext4 fs 后stat
显示将Modify:
9:45:00.000000000 +0100
Android 上的时区更改为 +3(可能卸载/重新插入 USB/重新安装以防万一),将同一文件复制到 ext4 上的其他位置,stat
显示
11:45:00.000000000 +0100
将 Linux 上的时区更改为+3。对于第二个副本stat
显示:
13:45:00.000000000 +0300
注意:当通过 GUI 按城市选择时区时(顺便说一句,我不知道 Linux 中的其他方式),由于日期保存的可能性,结果可能会或多或少相差一小时。
答案1
Android 上的原始时间戳:9:45:00.000000000 +0100
= 8:45:00 UTC。
将 Android 的时区更改为 +0300 并将文件传输到 Linux 后:
11:45:00.000000000 +0100
= 10:45:00 世界标准时间
MTP协议规范(ZIP 文件中的 MTPforUSB-IFv1.1.pdf 第 22 页)指示协议将时间戳处理为符合 ISO 8601 的日期时间字符串;然而不幸的是时区的指示选修的。
传输中时间戳发生变化的事实表明 Android MTP 实现并未使用实际的文件系统时间戳(可能采用 UTC 等效形式),而是使用 Android UI 中显示的本地化时间戳。
我发现发生此错误的三种可能机制:
- 安卓可以是错误地将本地化时间戳转换回 UTC用于传输使用当前的Android 时区,而不是传输已经采用 UTC 格式的原始文件系统时间戳。在这种情况下,Android MTP 实现将包括时间戳采用 UTC 格式的信息,Linux 实现也使用它。
- Android 使用 Android 中的本地时间传输时间戳当前的时区,但是不指定时区在 MTP DateTime 字符串中,导致 Linux 假定时间戳位于其自己的本地时区。
- Android使用Android当前时区的本地时间传输时间戳,并在DateTime字符串中指定时区,但Linux MTP实现不使用时区信息,假设有自己的本地时区。
使用 Wireshark + Linuxusbmon
内核模块转储 USB 流量应该能够确定错误原因。
在 Linux 上更改时区后的第二个副本:
13:45:00.000000000 +0300
= 10:45:00 世界标准时间 = 11:45:00 +0100
实际的 Linux 端时间戳(以及错误)与第一个副本中的完全相同,因为 13:45:00 +0300 和 11:45:00 +0100 都指同一时刻,即 10:世界标准时间 45:00。相同的时间戳只是使用不同的本地时区来呈现。
如果您查看 Linux 上第一个传输文件的时间戳,它的修改时间现在也应该为 13:45:00 +0300,因为所有针对本地时间格式化的时间戳现在都将使用 +0300 时区显示。