TOOL-Converting JSON DateTime String to .NET DateTime Structure
0 |
[Abstract] Sample code for converting "\/Date(1270051200000)\/" JSON format to .NET DateTime structure, it is used to convert log files with JSON-serialized data to make the date information readable.
專案裡有個Log機制會以JSON格式保存呼叫歷程中的參數物件,以便事後偵錯及追蹤之用。不過有個小困擾: 由於該Log模組採用JavaScriptSerializer進行序列化,DateTime型別會被格式化成"\/Date(1270051200000)\/"這種微軟獨創的日期表示格式(相關細節可參考舊文),在使用肉眼查看Log檔時,很難將其還原回時間,增加偵錯的難度。
我的構想是寫一個命令列轉檔程式,讀入Log檔並使用Regular Expression找出其中出現的"\/Date(1270051200000)\/"格式,將其置換成"2010/04/01T00:00:00Z"字串後輸出或另存檔案,用轉換後的檔案進行分析,即可避免JSON日期難以閱讀的問題。
在Javascript中,可輕易透過new Date(1270051200000)將"\/Date(1270051200000)\/"轉換成日期,在.NET內將其還原回DateTime時,則有一點小訣竅: Javascript中的tick是由1970/01/01 00:00:00起算的微秒(ms)數,而.NET的Ticks則是從0000/01/01 00:00:00起累計的100奈秒數(10ns, 等於千萬分之一秒),因此要經過轉換(乘上10,000再加上 621355968000000000, 1970/01/01 00:00:00的Ticks)才能算出正確時間。
以下是程式範例: (若要處理的檔案很大,用StringBuilder串接再一次寫入的做法會消耗大量記憶體,可考量改用StreamWriter讀一行寫一行的Streaming做法)
using System;
using System.Text.RegularExpressions;
using System.IO;
using System.Text;
namespace Darkthread
{
class Program
{
//getTime() in Javascript is milliseconds since January 1, 1970
//Ticks in .NET is nanoseconds since January 1, 0000
//new DateTime(1970, 1, 1).Ticks = 621355968000000000
static long baseTicks = 621355968000000000;
//Convert Javascript ticks to DateTime
static string GetDateTimeString(long jsTicks, int utcDiff = 0)
{
return new DateTime(jsTicks * 10000 + baseTicks).AddHours(utcDiff)
.ToString("yyyy/MM/ddTHH:mm:ssZ");
}
//Convert JSON date string to DateTime
static string GetDateTimeString(string jsonDateString)
{
int p = jsonDateString.IndexOf("(") + 1;
string numStr = jsonDateString.Substring(p,
jsonDateString.IndexOf(")") - p
);
int utcDiff = 0;
string[] a = numStr.Split('+', '-');
if (a.Length == 2)
{
utcDiff = (numStr.Contains("-") ? -1 : 1) *
int.Parse(a[1].Substring(0, 2));
numStr = a[0];
}
return GetDateTimeString(long.Parse(numStr), utcDiff);
}
static void Main(string[] args)
{
if (args.Length < 1 || args.Length > 2)
{
Console.WriteLine("Syntax: ConvJsonDate file_name or " +
"ConvJsonDate file_name_*.ext output_path");
return;
}
string fn = args[0];
string[] files = new string[] { fn };
//for wildcard search
if (fn.Contains("*"))
{
string srcFolder = Path.GetDirectoryName(fn);
//if no path assigned, use current folder
if (string.IsNullOrEmpty(srcFolder))
srcFolder = ".";
string pattern = Path.GetFileName(fn);
files = Directory.GetFiles(srcFolder, pattern);
}
//get output path if assigned
string path = args.Length > 1 ? args[1] : null;
//define regular expression pattern
Regex re = new Regex(@"\\/Date\([0-9+-]+\)\\/");
StringBuilder sb = new StringBuilder();
foreach (string f in files)
{
using (StreamReader sr = new StreamReader(f))
{
string line;
sb.Length = 0;
while ((line = sr.ReadLine()) != null)
//convert \/Date(....)\/ to yyyy-MM-ddTHH:mm:ssZ
sb.AppendLine(
re.Replace(line, (o) => GetDateTimeString(o.Value)));
if (string.IsNullOrEmpty(path))
//if no path assigned, output the converted text to console
Console.Write(sb.ToString());
else
//if path is assigned, dump the converted text to files
try
{
File.WriteAllText(Path.Combine(path, Path.GetFileName(f)),
sb.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return;
}
}
}
}
}
}
將程式編譯成JConvJsonDate.exe後,有以幾種應用方式:
- ConvJsonDate.exe boo.log
進行JSON日期轉換後顯示檔案內容 - ConvJsonDate.exe boo.log > foo.log
對boo.log進行JSON日期轉換後將結果存為foo.log - ConvJsonDate.exe x:\logs\*.log d:\ConvLogs
對x:\logs目錄下的所有*.log進行轉換,並將轉換結果以同樣檔名寫入d:\ConvLogs
Comments
Be the first to post a comment