C#下手动计算Unix时间戳问题
近期在研究wireshark抓包分析,每个.pcapng文件里包含 文件头+数据包头+数据包内容。其中Unix时间戳解析是一个问题。本文的目的即是根据时间戳获得数据包的绝对时间。
首先是时间戳的概念:
什么是时间戳?
(Unix)时间戳(英文为Unix epoch, Unix time, POSIX 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 }
通过上述方法获得的绝对时间跟时间有偏差。查了一些资料 后来发现这里面的年和月并不是严格的整数秒,所以不能这么计算。看网上有先获得天数,然后计算时分秒,自己试了一下,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文件解析后的数据发送到远程服务器端。
加油!!