2016年5月28日土曜日

VB ファイル日付の時刻精度

普段、ファイルを操作していると、気付かない、時刻の精度。
ファイルシステムの違いで、その秒精度が異なるのは有名ですが、
Visual Basic 等の言語で、日付 (DateTime) を 操作した場合にも、 これが当て嵌まります。
えっ、何の事!、 なんて仰らずにご覧下さい。


日付、特に、時刻を扱う場合に、留意しなければいけない その精度。

やれ、秒だの ミリ秒だの マイクロ秒だの ナノ秒だの。
そんな単位をお聴きになった方も多いと思います。
Tick の単位が 100 ナノ秒 なのは有名ですね。

因みに、一番簡単な、システムの時刻 (コンピューター上の現在の日時を現地時刻で表したもの) を取得して、
フル精度で表示して見ましょう。  Form で Label に表示とします。.
コードは、これ。

 Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim dtn As DateTime = DateTime.Now
         Me.Label1.Text = dtn.ToString("yyyy/MM/dd HH:mm:ss:fffffff")
    End Sub

End Class

実行して見れば、 秒の下に、7桁の 数値があります。   例えば、こんな感じ  2016/05/21 19:06:01:9361352 .
単位は 100 ナノ秒。

では、 ファイルのものは ... 。
NTFS 上では、 やはり、 同じ精度を持っています。  (Windows 10 の場合).


さて、 変数に この DateTime 構造体を取り込み、操作するとしましょう。
普通に使われる Control は DateTimePicker でしょうか。

既成のデータ(ファイルや時計)から取り込んだ場合には、 精度を保っています。
つまり、 丁度ではない、数字の羅列 が並びます。

しかし、 一旦、 DateTimePicker で日付の値を変えると、
さて .... 。
末尾の7桁は 0000000 に変わります。

通常の操作で、 0000000 が出現する確率は 1/10000000 ですね。
めったに現れない 数字の羅列 がお出まし になります。


何が言いたいかって、 ... 。
もし、単純にファイル時刻操作を行えば、 その時刻精度を調べれば ばれてしまう って事ですね。
ファイルひとつなら、珍しいね ... かも知れませんが、 フォルダ内のファイル全てがそうなら ばればれ ですよね。
でも、 Explorer や CommandPrompt から見ている分には、 この点に気付く事はありません。
何故なら、通常は 秒の精度があれば充分 だから。


開発環境をお持ちであれば、以下のソースコードを動かして見て下さい。
百聞は一見にしかず。



Public Class FormDTST
    Dim fn As String = ""

    Private Sub FormDTST_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        fn = "TestFile1.txt"      'Default: Project Content (File)
        Me.TextBox1.Text = fn
        GetTimeStamp()
        GetPickerStamp()

        Me.Label2Name.Text = "Create"
        Me.Label3Name.Text = "LastW."
        Me.Label4Name.Text = "Picker"

        Me.DateTimePicker1.Format = DateTimePickerFormat.Custom
        Me.DateTimePicker1.CustomFormat = "yyyy/MM/dd HH:mm:ss" 'ss:fffffff is invalid

        Me.NumericUpDown1.Enabled = False

        Me.AllowDrop = True

    End Sub

    Private Sub GetTimeStamp()
        fn = Me.TextBox1.Text
        Me.Label1.Text = fn
        Me.Label2.Text = IO.File.GetCreationTime(fn).ToString("yyyy/MM/dd HH:mm:ss:fffffff")
        Me.Label3.Text = IO.File.GetLastWriteTime(fn).ToString("yyyy/MM/dd HH:mm:ss:fffffff")
    End Sub

    Private Sub GetPickerStamp()
        Me.Label4.Text = Me.DateTimePicker1.Value.ToString("yyyy/MM/dd HH:mm:ss:fffffff")
    End Sub

    Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
        If IO.File.Exists(Me.TextBox1.Text) Then
            GetTimeStamp()
        End If
    End Sub

    Private Sub DateTimePicker1_ValueChanged(sender As Object, e As EventArgs) Handles DateTimePicker1.ValueChanged
        GetPickerStamp()
    End Sub

    Private Sub FormDTST_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Me.DragEnter
        If e.Data.GetDataPresent(DataFormats.FileDrop) Then
            e.Effect = DragDropEffects.Copy
        End If
    End Sub                             ' DragDropFile Cording(1/2)

    Private Sub FormDTST_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Me.DragDrop
        Dim filesfrom() As String = e.Data.GetData(DataFormats.FileDrop)
        Me.TextBox1.Text = filesfrom(0)                             'Top Only Drop
    End Sub                             ' DragDropFile Cording(2/2)

End Class


では、どうすれば ... 、 については、書かないで置きます。
ヒントは DateTimePicker 右隣りに置いた NumericUpDown 。
  実際には、
  汎用的に、これ(日付の変更)を実現してしまうと、
  アクセス権だのの例外や ソフトがファイル日付を個別に管理しているケースも有り、 一般的ではないとの判断です。
  つまり、簡単に変えられなかったり、変えてしまうと弊害が生じる、そんなケースもあるのです。.


まぁ、 実務には全く関係なさそうな 投稿 になってしまいました。
興味半分と言う事で ... 。



0 件のコメント:

コメントを投稿