实现思路:
使用状态管理(pinia)存储 timeZoneObject 的 key 值 利用 moment().utcOffset(key) 转化时间
// pinia 简单的使用 更多请参考官网
// store 目录结构
// stroe
// modules
// timeZoneStore.ts
// index.ts
// index.ts
import type { App } from 'vue';
import { createPinia } from 'pinia';
const store = createPinia();
export function setupStore(app: App<Element>) {
app.use(store);
}
export { store };
// main.ts 中引入 pinia
import { setupStore } from '@/store'
// 在 createApp 和 mount 间调用 setupStore(传入createApp生成的app对象)
setupStore(app)
// timeZoneStore.ts
import { defineStore } from 'pinia';
import { store } from '@/store';
import momentTZ from 'moment-timezone';
interface timeZoneModel {
timeZone: string;
}
export const timeZoneConfig = defineStore({
id: 'app-timeZone',
state: ():timeZoneModel => ({
timeZone: 'Asia/Shanghai',// 默认值 东八区
}),
actions: {
getTimeZoneString(date) {
// 根据时间戳 和时区key 计算出具体时区 返回具体时区的值:东八区 -08:00
const offsetutc = momentTZ.tz.zone(this.timeZone)?.utcOffset(date as any) as number;
const utc = 0 - offsetutc / 60;
return `${utc < 0 ? '-' : '+'}${Math.abs(utc) < 10 ? '0' + Math.abs(utc) : Math.abs(utc)}:00`;
}
}
})
export function useTimeZoneConfig() {
return timeZoneConfig(store);
}
格式化时间函数 dateUtil.ts
import moment from 'moment';
import { computed } from 'vue';
import { useTimeZoneConfig } from '@/store/modules/timeZoneStore';
const timeZoneConfig = useTimeZoneConfig ();
const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
const DATE_FORMAT = 'YYYY-MM-DD ';
export function formatToDateTimeFn(
date: moment.MomentInput = undefined,
format = DATE_TIME_FORMAT,
): string {
return moment(date).utcOffset(timeZoneConfig.getTimeZoneString(date)).format(format);
}
export function formatToDateFn(date: moment.MomentInput = undefined, format = DATE_FORMAT): string {
return moment(date).utcOffset(timeZoneConfig.getTimeZoneString(date)).format(format);
}
export const formatToDateTime = computed(() => (data) => {
return formatToDateTimeFn(data);
});
export const formatToDate = computed((data) => {
return formatToDateFn(data);
});
组件直接调用formatToDate / formatToDateTime 传入时间戳就可以显示当前时区所对应的时间
// 只显示年月日
<div>{{ formatToDate(时间戳) }}</div>
// 显示年月日时分秒
<div>{{ formatToDateTime(时间戳) }}</div>
基于 Ant Design Vue 写的下拉组件
// 时区下拉选择框
<div class="time-zone-select mr-3">
<a-select
ref="select"
v-model:value="timeZoneValue"
style="width: 400px"
@change="selectTimeZone"
>
<a-select-option v-for="item in timeZoneObject" :key="item.key" :value="item.key">{{
item.text
}}</a-select-option>
</a-select>
</div>
import { timeZoneObject } from 'zoneData.js'
import { useTimeZoneConfig } from '@/store/modules/timeZoneStore';
export default defineComponent({
setup(){
const timeZoneConfig = useTimeZoneConfig ();
const selectTimeZone = (val) => {
// 更新 timeZone 值
timeZoneConfig.$patch((state) => {
state.timeZone = val;
});
}
return {
timeZoneObject,
selectTimeZone
}
}
})
// zoneData.js
export const timeZoneObject = [
{ key: 'Pacific/Honolulu', text: '(UTC-10:00) 夏威夷' },
{ key: 'America/Anchorage', text: '(UTC-09:00) 安克雷奇' },
{ key: 'America/Santa_Isabel', text: '(UTC-08:00) 下加利福尼亚州' },
{ key: 'America/Los_Angeles', text: '(UTC-08:00) 太平洋时间(美国和加拿大)' },
{ key: 'America/Chihuahua', text: '(UTC-07:00) 奇瓦瓦,拉巴斯,马萨特兰' },
{ key: 'America/Phoenix', text: '(UTC-07:00) 亚利桑那' },
{ key: 'America/Denver', text: '(UTC-07:00) 山地时间(美国和加拿大)' },
{ key: 'America/Guatemala', text: '(UTC-06:00) 中美洲' },
{ key: 'America/Chicago', text: '(UTC-06:00) 中部时间(美国和加拿大)' },
{ key: 'America/Regina', text: '(UTC-06:00) 萨斯喀彻温' },
{ key: 'America/Mexico_City', text: '(UTC-06:00) 瓜达拉哈拉,墨西哥城,蒙特雷' },
{ key: 'America/Bogota', text: '(UTC-05:00) 波哥大,利马,基多' },
{ key: 'America/Indiana/Indianapolis', text: '(UTC-05:00) 印地安那州(东部)' },
{ key: 'America/New_York', text: '(UTC-05:00) 东部时间(美国和加拿大)' },
{ key: 'America/Caracas', text: '(UTC-04:30) 加拉加斯' },
{ key: 'America/Halifax', text: '(UTC-04:00) 大西洋时间(加拿大)' },
{ key: 'America/Asuncion', text: '(UTC-04:00) 亚松森' },
{ key: 'America/La_Paz', text: '(UTC-04:00) 乔治敦,拉巴斯,马瑙斯,圣胡安' },
{ key: 'America/Cuiaba', text: '(UTC-04:00) 库亚巴' },
{ key: 'America/Santiago', text: '(UTC-04:00) 圣地亚哥' },
{ key: 'America/St_Johns', text: '(UTC-03:30) 纽芬兰' },
{ key: 'America/Sao_Paulo', text: '(UTC-03:00) 巴西利亚' },
{ key: 'America/Godthab', text: '(UTC-03:00) 格陵兰' },
{ key: 'America/Cayenne', text: '(UTC-03:00) 卡宴,福塔雷萨' },
{ key: 'America/Argentina/Buenos_Aires', text: '(UTC-03:00) 布宜诺斯艾利斯' },
{ key: 'America/Montevideo', text: '(UTC-03:00) 蒙得维的亚' },
{ key: 'Etc/GMT+2', text: '(UTC-02:00) 协调世界时-2' },
{ key: 'Atlantic/Cape_Verde', text: '(UTC-01:00) 佛得角群岛' },
{ key: 'Atlantic/Azores', text: '(UTC-01:00) 亚速尔群岛' },
{ key: 'Africa/Casablanca', text: '(UTC+00:00) 卡萨布兰卡' },
{ key: 'Atlantic/Reykjavik', text: '(UTC+00:00) 蒙罗维亚,雷克雅未克' },
{ key: 'Europe/London', text: '(UTC+00:00) 都柏林,爱丁堡,里斯本,伦敦' },
{ key: 'Etc/GMT', text: '(UTC+00:00) 协调世界时' },
{ key: 'Europe/Berlin', text: '(UTC+01:00) 阿姆斯特丹,柏林,伯尔尼,罗马,斯德哥尔摩,维也纳' },
{ key: 'Europe/Paris', text: '(UTC+01:00) 布鲁塞尔,哥本哈根,马德里,巴黎' },
{ key: 'Africa/Lagos', text: '(UTC+01:00) 中非西部' },
{
key: 'Europe/Budapest',
text: '(UTC+01:00) 贝尔格莱德,布拉迪斯拉发,布达佩斯,卢布尔雅那,布拉格',
},
{ key: 'Europe/Warsaw', text: '(UTC+01:00) 萨拉热窝,斯科普里,华沙,萨格勒布' },
{ key: 'Africa/Windhoek', text: '(UTC+01:00) 温得和克' },
{ key: 'Europe/Istanbul', text: '(UTC+02:00) 雅典,布加勒斯特,伊斯坦布尔' },
{ key: 'Europe/Kiev', text: '(UTC+02:00) 赫尔辛基,基辅,里加,索非亚,塔林,维尔纽斯' },
{ key: 'Africa/Cairo', text: '(UTC+02:00) 开罗' },
{ key: 'Asia/Damascus', text: '(UTC+02:00) 大马士革' },
{ key: 'Asia/Amman', text: '(UTC+02:00) 安曼' },
{ key: 'Africa/Johannesburg', text: '(UTC+02:00) 哈拉雷,比勒陀利亚' },
{ key: 'Asia/Jerusalem', text: '(UTC+02:00) 耶路撒冷' },
{ key: 'Asia/Beirut', text: '(UTC+02:00) 贝鲁特' },
{ key: 'Asia/Baghdad', text: '(UTC+03:00) 巴格达' },
{ key: 'Europe/Minsk', text: '(UTC+03:00) 明斯克' },
{ key: 'Asia/Riyadh', text: '(UTC+03:00) 利雅得' },
{ key: 'Africa/Nairobi', text: '(UTC+03:00) 内罗毕' },
{ key: 'Asia/Tehran', text: '(UTC+03:30) 德黑兰' },
{ key: 'Europe/Moscow', text: '(UTC+04:00) 莫斯科,圣彼得堡,伏尔加格勒' },
{ key: 'Asia/Tbilisi', text: '(UTC+04:00) 第比利斯' },
{ key: 'Asia/Yerevan', text: '(UTC+04:00) 埃里温' },
{ key: 'Asia/Dubai', text: '(UTC+04:00) 阿布扎比,马斯喀特' },
{ key: 'Asia/Baku', text: '(UTC+04:00) 巴库' },
{ key: 'Indian/Mauritius', text: '(UTC+04:00) 路易港' },
{ key: 'Asia/Kabul', text: '(UTC+04:30) 喀布尔' },
{ key: 'Asia/Tashkent', text: '(UTC+05:00) 塔什干' },
{ key: 'Asia/Karachi', text: '(UTC+05:00) 伊斯兰堡,卡拉奇' },
{ key: 'Asia/Colombo', text: '(UTC+05:30) 斯里加亚渥登普拉' },
{ key: 'Asia/Kolkata', text: '(UTC+05:30) 钦奈,加尔各答,孟买,新德里' },
{ key: 'Asia/Kathmandu', text: '(UTC+05:45) 加德满都' },
{ key: 'Asia/Almaty', text: '(UTC+06:00) 阿斯塔纳' },
{ key: 'Asia/Dhaka', text: '(UTC+06:00) 达卡' },
{ key: 'Asia/Yekaterinburg', text: '(UTC+06:00) 叶卡捷琳堡' },
{ key: 'Asia/Yangon', text: '(UTC+06:30) 仰光' },
{ key: 'Asia/Bangkok', text: '(UTC+07:00) 曼谷,河内,雅加达' },
{ key: 'Asia/Novosibirsk', text: '(UTC+07:00) 新西伯利亚' },
{ key: 'Asia/Krasnoyarsk', text: '(UTC+08:00) 克拉斯诺亚尔斯克' },
{ key: 'Asia/Ulaanbaatar', text: '(UTC+08:00) 乌兰巴托' },
{ key: 'Asia/Shanghai', text: '(UTC+08:00) 北京,重庆,香港,乌鲁木齐' },
{ key: 'Australia/Perth', text: '(UTC+08:00) 佩思' },
{ key: 'Asia/Singapore', text: '(UTC+08:00) 吉隆坡,新加坡' },
{ key: 'Asia/Taipei', text: '(UTC+08:00) 台北' },
{ key: 'Asia/Irkutsk', text: '(UTC+09:00) 伊尔库茨克' },
{ key: 'Asia/Seoul', text: '(UTC+09:00) 首尔' },
{ key: 'Asia/Tokyo', text: '(UTC+09:00) 大阪,札幌,东京' },
{ key: 'Australia/Darwin', text: '(UTC+09:30) 达尔文' },
{ key: 'Australia/Adelaide', text: '(UTC+09:30) 阿德莱德' },
{ key: 'Australia/Hobart', text: '(UTC+10:00) 霍巴特' },
{ key: 'Asia/Yakutsk', text: '(UTC+10:00) 雅库茨克' },
{ key: 'Australia/Brisbane', text: '(UTC+10:00) 布里斯班' },
{ key: 'Pacific/Port_Moresby', text: '(UTC+10:00) 关岛,莫尔兹比港' },
{ key: 'Australia/Sydney', text: '(UTC+10:00) 堪培拉,墨尔本,悉尼' },
{ key: 'Asia/Vladivostok', text: '(UTC+11:00) 符拉迪沃斯托克' },
{ key: 'Pacific/Guadalcanal', text: '(UTC+11:00) 所罗门群岛,新喀里多尼亚' },
{ key: 'Etc/GMT-12', text: '(UTC+12:00) 协调世界时+12' },
{ key: 'Pacific/Fiji', text: '(UTC+12:00) 斐济,马绍尔群岛' },
{ key: 'Asia/Magadan', text: '(UTC+12:00) 马加丹' },
{ key: 'Pacific/Auckland', text: '(UTC+12:00) 奥克兰,惠灵顿' },
{ key: 'Pacific/Tongatapu', text: '(UTC+13:00) 努库阿洛法' },
{ key: 'Pacific/Apia', text: '(UTC+13:00) 萨摩亚群岛' },
];