-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtemp
More file actions
191 lines (177 loc) · 5.69 KB
/
temp
File metadata and controls
191 lines (177 loc) · 5.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
const syntaxCache = {};
const regExpMap = {
'y+':'(\\d{4})',
'M+':'(1[012]|0?[1-9])',
'd+':'(3[01]|[12]\\d|0?[1-9])',
'h+':'([01]?[0-9]|[2][0-3])',
'H+':'([01]?[0-9]|[2][0-3])',
'm+':'([0-5]?[0-9])',
's+':'([0-5]?[0-9])',
'q+':'(\\d)',
'S':'([\\d]{0,3})',
'W':'(.)'
};
const syntax = (format) => {
/**
* 检测一个字符串是否是一个有效的日期字符串
*/
//(\s+([01]?[0-9]|[2][0-3])) 小时
//(:+[0-5]?[0-9]) 分钟
//(:+[0-5]?[0-9]) 秒
//正向后行断言
//(小时(分钟|秒){0,2})?
let rexFormat=format;
let formatString=format||'';
if(rexFormat)
rexFormat = stringToRegExp(rexFormat);
else
rexFormat='^yyyy[\\-\\/]MM[\\-\\/]dd(?:(?:#0+hh)(?::mm)?(?::ss)?)?$';//#0 用于表述 特殊 字符 防止被转义[\\s|T]
let cache= syntaxCache[rexFormat];
if(!cache){
let rexs=[];//{key,match,format,index} {y+ yyyy (\\d{4}) 0 }
let keys=['d+','y+','M+','h+','H+','m+','s+'];//d 先进行匹配
for (let i = 0,len=keys.length; i < len; i++) {
let key=keys[i],value=regExpMap[key],match=new RegExp(key).exec(rexFormat);
if(match){
rexs.push({
key:key,
format:value,
match:match[0],
index:match.index
});
}
}
for (let i = 0,len=rexs.length; i<len; i++) {
let key=rexs[i].key;
formatString=formatString.replace(new RegExp(key),rexs[i].key);//标题名称格式化
rexFormat=rexFormat.replace(new RegExp(key),rexs[i].format);//能校验 真实日期格式
}
//((\s+([01]?[0-9]|[2][0-3]))(:+[0-5]?[0-9]){0,2})?
rexFormat=rexFormat.replace('#0','[\\s|T]');
syntaxCache[format]=cache={
rexFormat:new RegExp(rexFormat),
formatString:formatString,
rexs:rexs.sort(function(a,b){return a.index-b.index;})
};
}
cache.rexFormat.lastIndex=0;
return cache;
};
const dateFormat = (format,date) => {
format=format||'yyyy-MM-dd';
if(!date)return;
let result=syntax(format),
data={
'y+':date.getFullYear(),
'M+':date.getMonth()+1,
'd+':date.getDate(),
'h+':date.getHours(),
'H+':date.getHours(),
'm+':date.getMinutes(),
's+':date.getSeconds(),
'q+':Math.floor((date.getMonth()+3)/3),
'W':date.getDay()
};
let str=result.formatString,rexs=result.rexs;
for (let i = 0,len=rexs.length; i<len; i++) {
let rex=rexs[i],value=''+(data[rex.key]||'');
let subl=Math.max(rex.match.length,value.length);
value=('0000'+value).substr(-subl);
str=str.replace(rex.key,value);
}
data['value']=str;
return data;
};
// strZone 例如 +8000
const getZone = (strZone) => {
let zone = parseInt(strZone,0);
if(Math.isNaN(zone)) return null;
return Math.round(zone/100);
};
/**解析数据源 返回原始数据结构 */
const syntaxSource = (source,format) => {
let result=syntax(format),match,data;
match = result.rexFormat.exec(source);
if(match){
let rexs=result.rexs;
data={};
for (let i = 0,len=rexs.length; i<len; i++) {
data[rexs[i].key]=parseInt(match[i+1]);
}
}
return data;
};
const parseToDateSyntax = (source,format) => {
let data = syntaxSource(source,format);
if(!data) return;
let maxDay=31;
//对日需要做下额外验证 只不会超过31
switch(data['M+']){
case 4:case 6:case 9:case 11:{
maxDay=30;
break;
}
case 2:{
maxDay=28;
if((data['y+']%4==0&&data['y+']%100!=0)||data['y+']%400==0){//瑞年
maxDay++;
}
break;
}
}
if(data['d+']>maxDay)return null;
let match = /GMT([+-]\d+)/.exec(source);
return {
zone:getZone(match && match[1]),
value:new Date(data['y+']<100?0:data['y+'], (data['M+']||1) - 1, data['d+']||0, data['h+']||0, data['m+']||0, data['s+']||0,0)
};
};
const parseToDate = (source,format) => {
if(source instanceof Date || typeof source === 'number' || /^[+-]?[0-9]+$/.test(source)) {
return {
stamp:true,
value:new Date(Number(source))
};
}
/* /Date(1498320000000+0800)/ */
let match = /^\/Date\((\d+)([+-]\d+)?\)\/$/.exec(source);
if(match) {
return {
zone: getZone(match[2]),
stamp:true,
value:new Date(parseInt(match[1],10))
};
}
return parseToDateSyntax(source,format)
};
const stringToRegExp = (str) => {//将一段字符串 处理成有效的正则表达式 可支持的字符格式
return str.replace(/([[\]\\/.{}()?-])/gi,'\\$1');
};
// date 根据 zone 时区 进行对应的差值转换
const toZone = (date , zone ,k) => {
if(typeof zone !== 'number') return date;
let offset = (date.getTimezoneOffset() + zone * 60) * 60 * 1000;
if(offset === 0) return date;
return new Date(date.getTime() + k * offset);
};
/**
* 返回 为 date 时间戳表示 source 如果是时间表达形式 并且指明了时区,则转换为对应的时刻
* 指明了zone 则以zone时区所表达的时间 返回对应的时刻
*/
const parse = (source,format) => {
let result = parseToDate(source, format);
if(!result || !result.value) return;
if(!result.stamp) {// 不是时间戳格式 检查是否含有时区 因为转换出的时间 不是目标时间的时刻
return toZone(result.value,result.zone,-1);// 减少对应的差值时间 以方便标示出同样的时刻
}
return result.value;
};
// 存在 zone 则展示为 当前时刻[source]下 目标时区的时间
const format = (source, format, zone) => {
let date = parse(source);
if(date && zone !== null) {// 如果需要展示目标时区
date = toZone(date,zone,1);
}
if(!date) return '';
return dateFormat(format,date)['value'];
}