C#下手动计算Unix时间戳问题

近期在研究wireshark抓包分析,每个.pcapng文件里包含 文件头+数据包头+数据包内容。其中Unix时间戳解析是一个问题。本文的目的即是根据时间戳获得数据包的绝对时间。

首先是时间戳的概念:

什么是时间戳?

(Unix)时间戳(英文为Unix epochUnix timePOSIX time 或 Unix timestamp
是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒。
时间戳0按照ISO 8601格式写出来为 1970-01-01T00:00:00Z 。一小时为3600秒,一个基准日(也称纪元日,epoch day)是86400秒,闰秒没有计算在内.多数Unix系统将时间戳以一个32位整型进行保存,这可能会在2038年1月19日产生一些问题(Y2038问题)。

 

其他单位
1 分 60 秒
1 小时 3600 秒
1 天 86400 秒
1 周 604800 秒
1 月 (30.44 天) 2629743 秒
1 年 (365.24 天) 31556926 秒

(此内容来自http://shiningray.cn/toys/unix-timestamp#

本来自己是通过下面的方法,按 年 月 日 时 分 秒来获取。

 1 private string toUnix(int timeSecond)
 2 {
 3     string ans = "";
 4     const int stdMin=60,stdHour=3600,stdDay=86400,stdWeek=604800,stdMonth=2629743,stdYear=31556926;
 5     int year, month, day, hour, minite, second;
 6     year = timeSecond /stdYear;
 7     month = (timeSecond - year * stdYear) / stdMonth;
 8     day = (timeSecond - year * stdYear- month*stdMonth) /stdDay;
 9     hour = (timeSecond - year * stdYear - month * stdMonth-day* stdDay)/stdHour;
10     minite = (timeSecond - year * stdYear - month * stdMonth - day * stdDay-hour* stdHour)/stdMin;
11     second = (timeSecond - year * stdYear - month * stdMonth - day * stdDay - hour * stdHour-minite* stdMin) / 1;
12     Console.WriteLine(second - (timeSecond - year * stdYear - month * stdMonth - day * stdDay - hour * stdHour - minite * stdMin) / 1);
13     year += 1970;
14     month += 1;
15     day += 1;
16            
17     DateTime ts = new DateTime(year, month, day, hour, minite, second, 0);
18     ans = year.ToString() + "-" + month.ToString() + "-" + day.ToString() + "-" + hour.ToString() + ":" + minite.ToString() + ":" + second.ToString();
19     return ans;// ts.ToString();
20 }
View Code

 

通过上述方法获得的绝对时间跟时间有偏差。查了一些资料 后来发现这里面的年和月并不是严格的整数秒,所以不能这么计算。看网上有先获得天数,然后计算时分秒,自己试了一下,bingo。

代码如下:

private string toUnix(int timeSecond)
{
    string ans = "";
    const int stdMin = 60, stdHour = 3600, stdDay = 86400;
    int year, month, day, hour, minite, second;
            
    day = (timeSecond) / stdDay;
    hour = (timeSecond - day * stdDay) / stdHour;
    minite = (timeSecond -  day * stdDay - hour * stdHour) / stdMin;
    second = (timeSecond - day * stdDay - hour * stdHour - minite * stdMin) / 1;
    int sumDay = 0;

    for (year = 1970; ; year++)
    {
        if (isRunnian(year))
        {
            sumDay += 366;
            if (sumDay > day)
            {
                sumDay -= 366;
                break;
            }
        }
        else
        {
            sumDay += 365;
            if (sumDay > day)
            {
                sumDay -= 365;
                break;
            }
        }
    }
    month = 0;day-=sumDay;sumDay=0;
    if(isRunnian(year))
    {
        int[] dayOfMonth=new int[] {31 ,29, 31, 30, 31, 30 ,31 ,31, 30, 31,30,31 };
        for (int i=0;i<dayOfMonth.Length;i++)
        {
            sumDay += dayOfMonth[i];
            if (sumDay > day)
            {
                sumDay -= dayOfMonth[i];
                month = i;
                day -= sumDay;
                break;
            }
        }                
    }
    else
    {
        int[] dayOfMonth=new int[] {31 ,28, 31, 30, 31, 30 ,31 ,31, 30, 31,30,31 };
        for (int i=0;i<dayOfMonth.Length;i++)
        {
            sumDay += dayOfMonth[i];
            if (sumDay > day)
            {
                sumDay -= dayOfMonth[i];
                month = i;
                day -= sumDay;
                break;
            }
        }
    }
            
    ////year += 1970;
    month += 1;
    day += 1;
    ans = year.ToString() + "-" + month.ToString() + "-" + day.ToString() + "-" + hour.ToString() + ":" + minite.ToString() + ":" + second.ToString();
    return ans;// ts.ToString();
}

main函数里调用

int timeStamp=1374311155;//current timeStamp

string absoluteTime=toUnix(timeStamp);

即可。当然获取的是UTC时间,必要的话转换为东八区北京时间“东加西减”。

C#根据UnixTimeStamp获得绝对时间,欢迎交流~

自己接下来开始着手C#网络编程,将wireshark获取的.pcapng文件解析后的数据发送到远程服务器端。

加油!!

 

posted @ 2013-07-20 17:11  dancingwolves  阅读(1014)  评论(0)    收藏  举报