RFC822 的时间日期格式
Code
date-time = [ day "," ] date time ; dd mm yy
; hh:mm:ss zzz
day = "Mon" / "Tue" / "Wed" / "Thu"
/ "Fri" / "Sat" / "Sun"
date = 1*2DIGIT month 2DIGIT ; day month year
; e.g. 20 Jun 82
month = "Jan" / "Feb" / "Mar" / "Apr"
/ "May" / "Jun" / "Jul" / "Aug"
/ "Sep" / "Oct" / "Nov" / "Dec"
time = hour zone ; ANSI and Military
hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT]
; 00:00:00 - 23:59:59
zone = "UT" / "GMT" ; Universal Time
; North American : UT
/ "EST" / "EDT" ; Eastern: - 5/ - 4
/ "CST" / "CDT" ; Central: - 6/ - 5
/ "MST" / "MDT" ; Mountain: - 7/ - 6
/ "PST" / "PDT" ; Pacific: - 8/ - 7
/ 1ALPHA ; Military: Z = UT;
; A:-1; (J not used)
; M:-12; N:+1; Y:+12
/ ( ("+" / "-") 4DIGIT ) ; Local differential
; hours+min. (HHMM)
date-time = [ day "," ] date time ; dd mm yy
; hh:mm:ss zzz
day = "Mon" / "Tue" / "Wed" / "Thu"
/ "Fri" / "Sat" / "Sun"
date = 1*2DIGIT month 2DIGIT ; day month year
; e.g. 20 Jun 82
month = "Jan" / "Feb" / "Mar" / "Apr"
/ "May" / "Jun" / "Jul" / "Aug"
/ "Sep" / "Oct" / "Nov" / "Dec"
time = hour zone ; ANSI and Military
hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT]
; 00:00:00 - 23:59:59
zone = "UT" / "GMT" ; Universal Time
; North American : UT
/ "EST" / "EDT" ; Eastern: - 5/ - 4
/ "CST" / "CDT" ; Central: - 6/ - 5
/ "MST" / "MDT" ; Mountain: - 7/ - 6
/ "PST" / "PDT" ; Pacific: - 8/ - 7
/ 1ALPHA ; Military: Z = UT;
; A:-1; (J not used)
; M:-12; N:+1; Y:+12
/ ( ("+" / "-") 4DIGIT ) ; Local differential
; hours+min. (HHMM)
下面是根据上述标准对日期时间的解析
Code
1 virtual HRESULT ParseTime(const NWString& strMIMETime)
2 {
3 CString str = TEXT("AAAA");
4 CString strData(strMIMETime.c_str());
5 static const TCHAR * const lpszMonthName[] =
6 {TEXT("Jan"),TEXT("Feb"),TEXT("Mar"),TEXT("Apr"),TEXT("May"),
7 TEXT("Jun"),TEXT("Jul"),TEXT("Aug"),TEXT("Sep"),TEXT("Oct"),
8 TEXT("Nov"),TEXT("Dec")};
9
10 strData.Trim(); //删去多余的空格
11
12 INT nPosition = 0;
13 if(*(LPCTSTR(strData) + 3) == TEXT(',')) //星期信息无用,跳过。
14 {
15 nPosition = 5;
16 }
17
18 {//Fix bug: Microsoft NNTP Server return data format invalid,
19 //like "Tue,<SPACE><SPACE>26 May 2005
20
21 //We must detect and skip redundant SPACE.
22 while(*(LPCTSTR(strData) + nPosition) == TEXT(' '))
23 ++nPosition;
24 }
25
26 //天
27 CString strTemp = strData.Tokenize(TEXT(" "), nPosition);
28 UINT nDay = boost::lexical_cast<UINT>(LPCTSTR(strTemp));
29
30 //月
31 UINT nMonth = 0;
32 strTemp = strData.Tokenize(TEXT(" "), nPosition);
33 for(nMonth = 0; nMonth < 12; ++nMonth)
34 {
35 if(strTemp == lpszMonthName[nMonth])
36 break;
37 }
38
39 //年份
40 strTemp = LPCTSTR(strData.Tokenize(TEXT(" "), nPosition));
41 UINT nYear = boost::lexical_cast<UINT>(LPCTSTR(strTemp));
42
43 //小时
44 strTemp = LPCTSTR(strData.Tokenize(TEXT(":"), nPosition));
45 UINT nHour = boost::lexical_cast<UINT>(LPCTSTR(strTemp));
46
47 //分钟
48 strTemp = LPCTSTR(strData.Tokenize(TEXT(":"), nPosition));
49 UINT nMinute = boost::lexical_cast<UINT>(LPCTSTR(strTemp));
50
51 //秒数
52 UINT nSecond = 0;
53 if(*(LPCTSTR(strData) + nPosition - 1) == TEXT(':'))
54 {
55 strTemp = LPCTSTR(strData.Tokenize(TEXT(" "), nPosition));
56 nSecond = boost::lexical_cast<UINT>(LPCTSTR(strTemp));
57 }
58
59 //最后处理时区
60 time_t nZoneOffset = 0;
61 strTemp = strData.Tokenize(TEXT(" "), nPosition);
62 //UT,GMT,EST,EDT,CST,CDT,MST,MDT,PST,PDT
63 if(3 == strTemp.GetLength())
64 {
65 if(*(LPCTSTR(strTemp)) == TEXT('E') || *(LPCTSTR(strTemp)) == TEXT('e'))
66 {
67 if(*(LPCTSTR(strTemp) + 1) == TEXT('S') || *(LPCTSTR(strTemp) + 1) == TEXT('s'))
68 nZoneOffset = -5 * 60 * 60;
69 else//if(*(LPCTSTR(strTemp) + 1) == TEXT('D') || *(LPCTSTR(strTemp) + 1) == TEXT('d'))
70 nZoneOffset = -4 * 60 * 60;
71 }
72 else if(*(LPCTSTR(strTemp)) == TEXT('C') || *(LPCTSTR(strTemp)) == TEXT('c'))
73 {
74 if(*(LPCTSTR(strTemp) + 1) == TEXT('S') || *(LPCTSTR(strTemp) + 1) == TEXT('s'))
75 nZoneOffset = -6 * 60 * 60;
76 else//if(*(LPCTSTR(strTemp) + 1) == TEXT('D') || *(LPCTSTR(strTemp) + 1) == TEXT('d'))
77 nZoneOffset = -5 * 60 * 60;
78 }
79 else if(*(LPCTSTR(strTemp)) == TEXT('M') || *(LPCTSTR(strTemp)) == TEXT('m'))
80 {
81 if(*(LPCTSTR(strTemp) + 1) == TEXT('S') || *(LPCTSTR(strTemp) + 1) == TEXT('s'))
82 nZoneOffset = -7 * 60 * 60;
83 else//if(*(LPCTSTR(strTemp) + 1) == TEXT('D') || *(LPCTSTR(strTemp) + 1) == TEXT('d'))
84 nZoneOffset = -6 * 60 * 60;
85 }
86 else if(*(LPCTSTR(strTemp)) == TEXT('P') || *(LPCTSTR(strTemp)) == TEXT('p'))
87 {
88 if(*(LPCTSTR(strTemp) + 1) == TEXT('S') || *(LPCTSTR(strTemp) + 1) == TEXT('s'))
89 nZoneOffset = -8 * 60 * 60;
90 else//if(*(LPCTSTR(strTemp) + 1) == TEXT('D') || *(LPCTSTR(strTemp) + 1) == TEXT('d'))
91 nZoneOffset = -7 * 60 * 60;
92 }
93 else //GMT and UT, the nZoneOffset = 0
94 {}
95 }
96 //军方时区
97 else if(1 == strTemp.GetLength())
98 {
99 if(*(LPCTSTR(strTemp)) >= TEXT('A') && *(LPCTSTR(strTemp)) <= TEXT('F'))
100 nZoneOffset = -60 * 60 * (*(LPCTSTR(strTemp)) - TEXT('A') + 1);
101 else if(*(LPCTSTR(strTemp)) >= TEXT('K') && *(LPCTSTR(strTemp)) <= TEXT('M'))
102 nZoneOffset = -60 * 60 * (*(LPCTSTR(strTemp)) - TEXT('A') + 2);
103 else if(*(LPCTSTR(strTemp)) >= TEXT('N') && *(LPCTSTR(strTemp)) <= TEXT('Y'))
104 nZoneOffset = 60 * 60 * (*(LPCTSTR(strTemp)) - TEXT('N') + 1);
105 else if(*(LPCTSTR(strTemp)) >= TEXT('a') && *(LPCTSTR(strTemp)) <= TEXT('f'))
106 nZoneOffset = -60 * 60 * (*(LPCTSTR(strTemp)) - TEXT('a') + 1);
107 else if(*(LPCTSTR(strTemp)) >= TEXT('k') && *(LPCTSTR(strTemp)) <= TEXT('m'))
108 nZoneOffset = -60 * 60 * (*(LPCTSTR(strTemp)) - TEXT('a') + 2);
109 else if(*(LPCTSTR(strTemp)) >= TEXT('n') && *(LPCTSTR(strTemp)) <= TEXT('y'))
110 nZoneOffset = 60 * 60 * (*(LPCTSTR(strTemp)) - TEXT('n') + 1);
111 }
112 //数字时区
113 else
114 {
115 int nTimeZone = boost::lexical_cast<int>(LPCTSTR(strTemp));
116 nZoneOffset = (60 * (nTimeZone / 100) + nTimeZone % 100) * 60;
117 }
118
119 struct tm tmRet = {nSecond, nMinute, nHour, nDay, nMonth, nYear, 0, 0, -1};
120 /**//* Fix up the year, using the RFC 2822 rules. Remember that tm_year stores the year - 1900. */
121 if (tmRet.tm_year < 50)
122 tmRet.tm_year += 100;
123 else if(tmRet.tm_year >= 1000)
124 tmRet.tm_year -= 1900;
125
126 m_tm = _mkgmtime(&tmRet) - nZoneOffset;
127 return S_OK;
128 }
1 virtual HRESULT ParseTime(const NWString& strMIMETime)
2 {
3 CString str = TEXT("AAAA");
4 CString strData(strMIMETime.c_str());
5 static const TCHAR * const lpszMonthName[] =
6 {TEXT("Jan"),TEXT("Feb"),TEXT("Mar"),TEXT("Apr"),TEXT("May"),
7 TEXT("Jun"),TEXT("Jul"),TEXT("Aug"),TEXT("Sep"),TEXT("Oct"),
8 TEXT("Nov"),TEXT("Dec")};
9
10 strData.Trim(); //删去多余的空格
11
12 INT nPosition = 0;
13 if(*(LPCTSTR(strData) + 3) == TEXT(',')) //星期信息无用,跳过。
14 {
15 nPosition = 5;
16 }
17
18 {//Fix bug: Microsoft NNTP Server return data format invalid,
19 //like "Tue,<SPACE><SPACE>26 May 2005
20
21 //We must detect and skip redundant SPACE.
22 while(*(LPCTSTR(strData) + nPosition) == TEXT(' '))
23 ++nPosition;
24 }
25
26 //天
27 CString strTemp = strData.Tokenize(TEXT(" "), nPosition);
28 UINT nDay = boost::lexical_cast<UINT>(LPCTSTR(strTemp));
29
30 //月
31 UINT nMonth = 0;
32 strTemp = strData.Tokenize(TEXT(" "), nPosition);
33 for(nMonth = 0; nMonth < 12; ++nMonth)
34 {
35 if(strTemp == lpszMonthName[nMonth])
36 break;
37 }
38
39 //年份
40 strTemp = LPCTSTR(strData.Tokenize(TEXT(" "), nPosition));
41 UINT nYear = boost::lexical_cast<UINT>(LPCTSTR(strTemp));
42
43 //小时
44 strTemp = LPCTSTR(strData.Tokenize(TEXT(":"), nPosition));
45 UINT nHour = boost::lexical_cast<UINT>(LPCTSTR(strTemp));
46
47 //分钟
48 strTemp = LPCTSTR(strData.Tokenize(TEXT(":"), nPosition));
49 UINT nMinute = boost::lexical_cast<UINT>(LPCTSTR(strTemp));
50
51 //秒数
52 UINT nSecond = 0;
53 if(*(LPCTSTR(strData) + nPosition - 1) == TEXT(':'))
54 {
55 strTemp = LPCTSTR(strData.Tokenize(TEXT(" "), nPosition));
56 nSecond = boost::lexical_cast<UINT>(LPCTSTR(strTemp));
57 }
58
59 //最后处理时区
60 time_t nZoneOffset = 0;
61 strTemp = strData.Tokenize(TEXT(" "), nPosition);
62 //UT,GMT,EST,EDT,CST,CDT,MST,MDT,PST,PDT
63 if(3 == strTemp.GetLength())
64 {
65 if(*(LPCTSTR(strTemp)) == TEXT('E') || *(LPCTSTR(strTemp)) == TEXT('e'))
66 {
67 if(*(LPCTSTR(strTemp) + 1) == TEXT('S') || *(LPCTSTR(strTemp) + 1) == TEXT('s'))
68 nZoneOffset = -5 * 60 * 60;
69 else//if(*(LPCTSTR(strTemp) + 1) == TEXT('D') || *(LPCTSTR(strTemp) + 1) == TEXT('d'))
70 nZoneOffset = -4 * 60 * 60;
71 }
72 else if(*(LPCTSTR(strTemp)) == TEXT('C') || *(LPCTSTR(strTemp)) == TEXT('c'))
73 {
74 if(*(LPCTSTR(strTemp) + 1) == TEXT('S') || *(LPCTSTR(strTemp) + 1) == TEXT('s'))
75 nZoneOffset = -6 * 60 * 60;
76 else//if(*(LPCTSTR(strTemp) + 1) == TEXT('D') || *(LPCTSTR(strTemp) + 1) == TEXT('d'))
77 nZoneOffset = -5 * 60 * 60;
78 }
79 else if(*(LPCTSTR(strTemp)) == TEXT('M') || *(LPCTSTR(strTemp)) == TEXT('m'))
80 {
81 if(*(LPCTSTR(strTemp) + 1) == TEXT('S') || *(LPCTSTR(strTemp) + 1) == TEXT('s'))
82 nZoneOffset = -7 * 60 * 60;
83 else//if(*(LPCTSTR(strTemp) + 1) == TEXT('D') || *(LPCTSTR(strTemp) + 1) == TEXT('d'))
84 nZoneOffset = -6 * 60 * 60;
85 }
86 else if(*(LPCTSTR(strTemp)) == TEXT('P') || *(LPCTSTR(strTemp)) == TEXT('p'))
87 {
88 if(*(LPCTSTR(strTemp) + 1) == TEXT('S') || *(LPCTSTR(strTemp) + 1) == TEXT('s'))
89 nZoneOffset = -8 * 60 * 60;
90 else//if(*(LPCTSTR(strTemp) + 1) == TEXT('D') || *(LPCTSTR(strTemp) + 1) == TEXT('d'))
91 nZoneOffset = -7 * 60 * 60;
92 }
93 else //GMT and UT, the nZoneOffset = 0
94 {}
95 }
96 //军方时区
97 else if(1 == strTemp.GetLength())
98 {
99 if(*(LPCTSTR(strTemp)) >= TEXT('A') && *(LPCTSTR(strTemp)) <= TEXT('F'))
100 nZoneOffset = -60 * 60 * (*(LPCTSTR(strTemp)) - TEXT('A') + 1);
101 else if(*(LPCTSTR(strTemp)) >= TEXT('K') && *(LPCTSTR(strTemp)) <= TEXT('M'))
102 nZoneOffset = -60 * 60 * (*(LPCTSTR(strTemp)) - TEXT('A') + 2);
103 else if(*(LPCTSTR(strTemp)) >= TEXT('N') && *(LPCTSTR(strTemp)) <= TEXT('Y'))
104 nZoneOffset = 60 * 60 * (*(LPCTSTR(strTemp)) - TEXT('N') + 1);
105 else if(*(LPCTSTR(strTemp)) >= TEXT('a') && *(LPCTSTR(strTemp)) <= TEXT('f'))
106 nZoneOffset = -60 * 60 * (*(LPCTSTR(strTemp)) - TEXT('a') + 1);
107 else if(*(LPCTSTR(strTemp)) >= TEXT('k') && *(LPCTSTR(strTemp)) <= TEXT('m'))
108 nZoneOffset = -60 * 60 * (*(LPCTSTR(strTemp)) - TEXT('a') + 2);
109 else if(*(LPCTSTR(strTemp)) >= TEXT('n') && *(LPCTSTR(strTemp)) <= TEXT('y'))
110 nZoneOffset = 60 * 60 * (*(LPCTSTR(strTemp)) - TEXT('n') + 1);
111 }
112 //数字时区
113 else
114 {
115 int nTimeZone = boost::lexical_cast<int>(LPCTSTR(strTemp));
116 nZoneOffset = (60 * (nTimeZone / 100) + nTimeZone % 100) * 60;
117 }
118
119 struct tm tmRet = {nSecond, nMinute, nHour, nDay, nMonth, nYear, 0, 0, -1};
120 /**//* Fix up the year, using the RFC 2822 rules. Remember that tm_year stores the year - 1900. */
121 if (tmRet.tm_year < 50)
122 tmRet.tm_year += 100;
123 else if(tmRet.tm_year >= 1000)
124 tmRet.tm_year -= 1900;
125
126 m_tm = _mkgmtime(&tmRet) - nZoneOffset;
127 return S_OK;
128 }