背景
注:存在问题,需要修改,等修改完成会把这段话去掉
(吐槽一下,不要相信后端返回的数据格式就一定是你需要的格式,前端要做兼容处理避免因为后端数据问题导致报错)
在原有项目基础上增加时区功能,意味着所有需要时间查询和时间返回的地方都要进行时区处理,要么前端处理要么后端处理,我所能想到的就是两种方案:
1、在请求头里面带上时区,后端返回就是处理后的值
2、纯前端处理,后端返回都是用的服务器时间,用户展示根据不同时区做不同展示
但是还有其他问题,ui框架用的elementui
1、这个时间组件本身应该永远用的国际标准时间,但是后端返回不是国际标准时间,所以查询时的时间处理和响应时的时间处理应该不一致
2、不同接口所需传参字段相同可能值的格式不同,相同字段可能有的需要处理也可能不需要。
建议
因为前端展示可能与实际后端返回值有出入,所以为了不因为时区处理的问题导致设计修改时导致后端数据库内的数据出现问题,那么我的处理方式是时区的查询处理放在请求拦截逻辑里面,但是数据展示时对时区的处理还是放在拿到数据时的具体页面上,并且不要进行赋值,不要赋值,只要展示时进行转化就行了
备注
我的时区值是存在cookies中的,下面展示我的时区列表,在我的代码里面写了个默认值为8,代表就是下方code为8对应的时区,进行计算时传参我给了默认值0的国际时间,如果需要改,传参从下方code值中选择就行了。时区选择组件就不做展示了,无非就是用下方数据做一个下拉列表,用户勾选后将这个值存下来。之后代码里面的area和local都为这里的code值
import Cookies from "js-cookie";
let defaultSwitchList = [
{
name: "startTime",
isHandle: true,
time: "00:00:00",
},
{
name: "endTime",
isHandle: true,
time: "23:59:59",
},
{
name:"dateTime",
isHandle: true,
}
];
//需要注意的点
//1、尽量不改变原有参数
//2、在vue文件中尽量只存在交互逻辑,所有数据的处理放在vue文件外处理
//3、这个时间格式原来传的是什么格式返回就是什么格式
//4、这个时间格式原来传的是什么格式返回就是什么格式
// time时间值
// local现在时间的时区
// area想要转成的时区
function switchTimeZoneFigure(time, local, area, config) {
if (!time) return time;
time = String(time);
if (time.indexOf("-") != -1 || time.indexOf(":") != -1) {
//这里这个判断不严谨,有存在这个符号也不代表值就是有年月日,也可能只传了年月或者其他不是日期的字符串
if (time.indexOf("-") == -1) {
throw new Error("时间必须包含年月日时间");
}
if (time.indexOf(":") != -1) {
return stringChange(time, local, area);
} else {
if(config&&config.time){
time += config.time;
return stringChange(time, local, area,true);
}else{
return time
}
}
} else {
return timeStampChange(time, local, area);
}
}
// 时间撮转换
function timeStampChange(time, local, area) {
return time - 0 + (area - local) * 3600000;
}
// 字符串转换
//这个local没用到,因为服务器时区就是按零时区给的时间,所以不需要参与运算,如果要参与运算
//const resultTime = d.getTime()+ (local+ area) * 3600000;
function stringChange(time, local, area,onlyYMD=false) {
const d = new Date(time);
const resultTime = d.getTime() + area * 3600000;
const date = new Date(resultTime);
const year = date.getFullYear();
const month =
date.getMonth() + 1 < 10
? "0" + (date.getMonth() + 1)
: date.getMonth() + 1;
const day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
const hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
const minutes =
date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
const seconds =
date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
if(onlyYMD){
return year + "-" + month + "-" + day
}
return (
year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds
);
}
// 用于切换时区时判断当前需要做因时区改变而对时间进行处理,如果需要处理才会调用上面的时间处理函数
// switchList是用于判断有哪些参数字段需要做时区转换,为了避免同一字段出现转与不转的情况,所以加了一个isHandle参数用来判断,不传的时候走默认配置,如果出现了最好在请求拦截时通过接口地址来判断进行配置的修改
// queryData是用于数据的整体形参,如果数据不合规还是原来的数据返回
// local这个参数是查询时的现在所用时间时区,因为项目中用的国际时间,所以不想传参控制就给了个默认值
// item这是为了当数据缺少时分秒时,进行拼接默认值时去查找对应的默认拼接值
// 这里拿时区值直接用的cookies,如果可以最好用vuex拿,因为默认值这里就存在了两个,修改就需要改两个地方,但是为了避免这里引入不更新,先用cookie实现
//assign的处理是为了避免函数间的传参还是用的同一个参,导致这里的处理污染原有数据
function switchTimeZone(queryData, switchList = defaultSwitchList, local = 0) {
//对象去重
switchList=Array.from(new Set(switchList.map(item => JSON.stringify(item)))).map(item => JSON.parse(item))
if (queryData && typeof queryData === "object" && queryData !== null) {
let flag = switchList.find((item) => {
for (let key in queryData) {
if (key == item.name && item.isHandle) {
return true;
}
}
return false;
});
if (flag) {
let area = Cookies.get("timeZone") || 8;
let param = Object.assign({}, queryData);
switchList.forEach((item) => {
for (let key in param) {
if (item.name == key && item.isHandle) {
param[key] = switchTimeZoneFigure(queryData[key], local, area, item);
}
}
});
return param;
}
}
return queryData;
}
//提供方法对时间进行年月日的转换
function initializeFormat(time) {
if (!time) return "";
let date = new Date(Number(time));
let year = date.getFullYear();
let month =
date.getMonth() + 1 < 10
? "0" + (date.getMonth() + 1)
: date.getMonth() + 1;
let day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
let hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
let minutes =
date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
let seconds =
date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
return (
year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds
);
}
export { switchTimeZone, switchTimeZoneFigure,initializeFormat };