Appearance
实现 Unix 时间戳转换器 工具
分类:developer | 标签:时间戳、时间、时区、转换 时间戳与可读时间互转,自动识别秒/毫秒,支持多时区
2.1 功能说明
时间戳与可读时间互转,自动识别秒/毫秒,支持多时区
2.1.1 使用指南
使用指导
Unix 时间戳是从 1970-01-01 00:00:00 UTC 起经过的秒数(或毫秒数)。前端/后端接口常用它传递时间。
秒 vs 毫秒
JavaScript 的 Date.now() 返回毫秒(13 位),而多数后端接口用秒(10 位)。本工具自动识别位数。
时区
时间戳本身是绝对时刻,与时间 zone 无关;展示时区仅影响"可读时间"的显示。
2.2 代码实现
2.2.1 组件结构
本工具是一个基于 Vue 3 <script setup> 语法的单文件组件(SFC),统一包裹在 ToolPageShell 组件内,由它提供页面标题、工具 ID、分类与「使用指南」插槽等通用外壳;核心业务逻辑(响应式状态、计算属性、事件处理函数)全部写在 <script setup> 中,输入/输出通过 el-input、el-button 等 Element Plus 组件与用户交互,所有数据均在浏览器本地处理,不会上传服务器。
2.2.2 核心逻辑概览
<script setup> 中定义的主要函数/方法:
tick()fmt()tsToDate()dateToTs()
2.2.3 关键实现代码
以下是该工具的完整 <script setup> 实现(核心代码)。模板(<template>)与样式(<style>)已省略。
vue
import { ref, computed, onMounted, onUnmounted } from 'vue'
import ToolPageShell from '@/components/ToolPageShell.vue'
const zones = [
{ label: 'UTC', value: 'UTC' },
{ label: '北京 (UTC+8)', value: 'Asia/Shanghai' },
{ label: '东京 (UTC+9)', value: 'Asia/Tokyo' },
{ label: '纽约 (UTC-5/-4)', value: 'America/New_York' },
{ label: '伦敦 (UTC+0/+1)', value: 'Europe/London' },
{ label: '洛杉矶 (UTC-8/-7)', value: 'America/Los_Angeles' }
]
const tsInput = ref('')
const tsUnit = ref('auto')
const tz = ref('Asia/Shanghai')
const tz2 = ref('Asia/Shanghai')
const dateVal = ref('')
const tsError = ref('')
const localStr = ref('')
const utcStr = ref('')
const zonedStr = ref('')
const secStr = ref('')
const msStr = ref('')
const nowSec = ref(0)
const nowMs = ref(0)
const tzLabel = computed(() => zones.find((z) => z.value === tz.value)?.label || '时区')
let timer = null
function tick() {
nowSec.value = Math.floor(Date.now() / 1000)
nowMs.value = Date.now()
}
function fmt(d, zone) {
try {
return new Intl.DateTimeFormat('zh-CN', {
timeZone: zone,
year: 'numeric', month: '2-digit', day: '2-digit',
hour: '2-digit', minute: '2-digit', second: '2-digit',
hour12: false
}).format(d)
} catch {
return d.toISOString().replace('T', ' ').slice(0, 19)
}
}
function tsToDate() {
tsError.value = ''
localStr.value = utcStr.value = zonedStr.value = ''
const raw = tsInput.value.trim()
if (raw === '') return
const n = Number(raw)
if (!Number.isFinite(n)) { tsError.value = '时间戳必须是数字'; return }
let ms = n
if (tsUnit.value === 's') ms = n * 1000
else if (tsUnit.value === 'ms') ms = n
else {
// 自动识别:10 位为秒,13 位为毫秒
ms = Math.abs(n) >= 1e12 ? n : n * 1000
}
const d = new Date(ms)
if (isNaN(d.getTime())) { tsError.value = '时间戳超出有效范围'; return }
localStr.value = fmt(d, undefined)
utcStr.value = fmt(d, 'UTC')
zonedStr.value = fmt(d, tz.value)
}
function dateToTs() {
if (!dateVal.value) { secStr.value = msStr.value = ''; return }
// dateVal 为本地输入;若选择非本地时区,需按该时区偏移换算 UTC 毫秒
const base = new Date(dateVal.value.replace(' ', 'T'))
let ms = base.getTime()
if (tz2.value !== Intl.DateTimeFormat().resolvedOptions().timeZone) {
// 计算目标时区相对 UTC 的偏移
const parts = new Intl.DateTimeFormat('en-US', {
timeZone: tz2.value, year: 'numeric', month: '2-digit', day: '2-digit',
hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false
}).formatToParts(base)
const map = {}
parts.forEach((p) => (map[p.type] = p.value))
const asUtc = Date.UTC(+map.year, +map.month - 1, +map.day, +map.hour, +map.minute, +map.second)
ms = asUtc
}
secStr.value = Math.floor(ms / 1000)
msStr.value = ms
}
function useNow() {
tsInput.value = String(Math.floor(Date.now() / 1000))
tsUnit.value = 'auto'
tsToDate()
}
onMounted(() => { tick(); timer = setInterval(tick, 1000) })
onUnmounted(() => clearInterval(timer))2.3 效果截图
