# 日期處理模塊
日期處理模塊提供了日期格式化、時(shí)間戳轉(zhuǎn)換、年齡計(jì)算、閏年判斷等常用的日期時(shí)間處理功能。
## 引用方式
### ES6 模塊引用
```javascript
import sinma from 'sinmajs';
// 或者使用解構(gòu)賦值
import { formatDate, calculateAge, isLeapYear, now } from 'sinmajs';
```
### CommonJS 引用
```javascript
const sinma = require('sinmajs');
```
### 瀏覽器直接引用
```html
<script src="https://unpkg.com/sinmajs@latest/dist/sinma.min.js"></script>
<script>
// 直接使用 sinma 對象
console.log(sinma.formatDate(new Date(), 'YYYY-MM-DD'));
</script>
```
## API 列表
### formatDate(date, format) - 日期格式化
將日期對象或日期字符串格式化為指定格式的字符串。
#### 參數(shù)
- `date` {Date|string|number} - 日期對象、日期字符串或時(shí)間戳
- `format` {string} - 格式化模板,默認(rèn) `'YYYY-MM-DD'`
#### 格式化符號
- `YYYY` - 四位年份
- `MM` - 兩位月份(01-12)
- `DD` - 兩位日期(01-31)
- `HH` - 兩位小時(shí)(00-23)
- `mm` - 兩位分鐘(00-59)
- `ss` - 兩位秒鐘(00-59)
#### 返回值
- {string} - 格式化后的日期字符串,無效日期返回空字符串
#### 功能代碼
```javascript
function formatDate(date, format = 'YYYY-MM-DD') {
const d = new Date(date);
if (isNaN(d.getTime())) return '';
const year = d.getFullYear();
const month = String(d.getMonth() + 1).padStart(2, '0');
const day = String(d.getDate()).padStart(2, '0');
const hours = String(d.getHours()).padStart(2, '0');
const minutes = String(d.getMinutes()).padStart(2, '0');
const seconds = String(d.getSeconds()).padStart(2, '0');
return format
.replace('YYYY', year)
.replace('MM', month)
.replace('DD', day)
.replace('HH', hours)
.replace('mm', minutes)
.replace('ss', seconds);
}
```
#### 使用方法
```javascript
const now = new Date();
sinma.formatDate(now); // '2023-12-25'
sinma.formatDate(now, 'YYYY-MM-DD HH:mm:ss'); // '2023-12-25 14:30:45'
sinma.formatDate(now, 'MM/DD/YYYY'); // '12/25/2023'
sinma.formatDate(now, 'YYYY年MM月DD日'); // '2023年12月25日'
sinma.formatDate('2023-06-15'); // '2023-06-15'
sinma.formatDate(1703505045000); // '2023-12-25'
sinma.formatDate('invalid'); // ''
```
#### 使用范例
```javascript
// 文章發(fā)布時(shí)間顯示
function formatPublishTime(timestamp) {
const now = new Date();
const publishDate = new Date(timestamp);
const diffMs = now - publishDate;
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
if (diffDays === 0) {
return '今天 ' + sinma.formatDate(publishDate, 'HH:mm');
} else if (diffDays === 1) {
return '昨天 ' + sinma.formatDate(publishDate, 'HH:mm');
} else if (diffDays < 7) {
return `${diffDays}天前`;
} else {
return sinma.formatDate(publishDate, 'YYYY-MM-DD');
}
}
// 日志記錄格式化
function createLogEntry(level, message) {
const timestamp = sinma.formatDate(new Date(), 'YYYY-MM-DD HH:mm:ss');
return `[${timestamp}] [${level.toUpperCase()}] ${message}`;
}
console.log(createLogEntry('info', '用戶登錄成功'));
// [2023-12-25 14:30:45] [INFO] 用戶登錄成功
// 文件名生成
function generateFileName(prefix, extension = 'log') {
const timestamp = sinma.formatDate(new Date(), 'YYYYMMDD_HHmmss');
return `${prefix}_${timestamp}.${extension}`;
}
console.log(generateFileName('backup', 'sql'));
// backup_20231225_143045.sql
// 報(bào)表日期范圍
function formatDateRange(startDate, endDate) {
const start = sinma.formatDate(startDate, 'YYYY年MM月DD日');
const end = sinma.formatDate(endDate, 'YYYY年MM月DD日');
return `${start} 至 ${end}`;
}
```
---
### getTimestamp(date) - 獲取時(shí)間戳
將日期轉(zhuǎn)換為毫秒級時(shí)間戳。
#### 參數(shù)
- `date` {Date|string} - 日期對象或日期字符串
#### 返回值
- {number} - 毫秒級時(shí)間戳
#### 功能代碼
```javascript
function getTimestamp(date) {
return new Date(date).getTime();
}
```
#### 使用方法
```javascript
sinma.getTimestamp(new Date()); // 1703505045000
sinma.getTimestamp('2023-12-25'); // 1703462400000
sinma.getTimestamp('2023-12-25 14:30'); // 1703505000000
```
#### 使用范例
```javascript
// 緩存過期檢查
function isCacheExpired(cacheTimestamp, expireMinutes = 30) {
const now = sinma.getTimestamp(new Date());
const expireTime = cacheTimestamp + (expireMinutes * 60 * 1000);
return now > expireTime;
}
// API 請求去重
const requestCache = new Map();
function makeUniqueRequest(url, data) {
const key = url + JSON.stringify(data);
const cached = requestCache.get(key);
if (cached && !isCacheExpired(cached.timestamp, 5)) {
return Promise.resolve(cached.response);
}
return fetch(url, { method: 'POST', body: JSON.stringify(data) })
.then(response => response.json())
.then(result => {
requestCache.set(key, {
response: result,
timestamp: sinma.getTimestamp(new Date())
});
return result;
});
}
// 性能監(jiān)控
class PerformanceMonitor {
constructor() {
this.startTime = null;
}
start() {
this.startTime = sinma.getTimestamp(new Date());
}
end(operationName) {
const endTime = sinma.getTimestamp(new Date());
const duration = endTime - this.startTime;
console.log(`${operationName} 耗時(shí): ${duration}ms`);
return duration;
}
}
```
---
### calculateAge(birthday) - 計(jì)算年齡
根據(jù)生日字符串計(jì)算當(dāng)前年齡。
#### 參數(shù)
- `birthday` {string} - 生日字符串(如:'1990-01-01')
#### 返回值
- {number} - 年齡(歲),最小為0
#### 功能代碼
```javascript
function calculateAge(birthday) {
const birth = new Date(birthday);
const today = new Date();
let age = today.getFullYear() - birth.getFullYear();
if (today.getMonth() < birth.getMonth() ||
(today.getMonth() === birth.getMonth() && today.getDate() < birth.getDate())) {
age--;
}
return Math.max(0, age);
}
```
#### 使用方法
```javascript
sinma.calculateAge('1990-01-01'); // 33 (假設(shè)當(dāng)前是2023年)
sinma.calculateAge('2000-12-25'); // 23
sinma.calculateAge('2023-06-15'); // 0 (當(dāng)年出生)
sinma.calculateAge('2025-01-01'); // 0 (未來日期返回0)
```
#### 使用范例
```javascript
// 用戶信息顯示
function formatUserProfile(user) {
return {
name: user.name,
age: sinma.calculateAge(user.birthday),
ageGroup: getAgeGroup(sinma.calculateAge(user.birthday)),
birthday: sinma.formatDate(user.birthday, 'MM月DD日')
};
}
function getAgeGroup(age) {
if (age < 18) return '未成年';
if (age < 35) return '青年';
if (age < 60) return '中年';
return '老年';
}
// 生日提醒
function getBirthdayReminder(users) {
const today = new Date();
const todayStr = sinma.formatDate(today, 'MM-DD');
return users
.filter(user => {
const birthday = sinma.formatDate(user.birthday, 'MM-DD');
return birthday === todayStr;
})
.map(user => ({
name: user.name,
age: sinma.calculateAge(user.birthday),
message: `今天是 ${user.name} 的生日,${sinma.calculateAge(user.birthday)} 歲生日快樂!`
}));
}
// 年齡統(tǒng)計(jì)分析
function analyzeAgeDistribution(users) {
const ageGroups = {
'0-17': 0,
'18-30': 0,
'31-45': 0,
'46-60': 0,
'60+': 0
};
users.forEach(user => {
const age = sinma.calculateAge(user.birthday);
if (age < 18) ageGroups['0-17']++;
else if (age <= 30) ageGroups['18-30']++;
else if (age <= 45) ageGroups['31-45']++;
else if (age <= 60) ageGroups['46-60']++;
else ageGroups['60+']++;
});
return ageGroups;
}
// 保險(xiǎn)費(fèi)率計(jì)算
function calculateInsurancePremium(birthday, coverageAmount) {
const age = sinma.calculateAge(birthday);
let rate = 0.01; // 基礎(chǔ)費(fèi)率 1%
if (age < 25) rate = 0.008;
else if (age < 35) rate = 0.01;
else if (age < 50) rate = 0.015;
else rate = 0.02;
return {
age: age,
rate: `${rate * 100}%`,
premium: sinma.formatCurrency(coverageAmount * rate)
};
}
```
---
### isLeapYear(year) - 閏年判斷
判斷指定年份是否為閏年。
#### 參數(shù)
- `year` {number} - 年份
#### 返回值
- {boolean} - 是閏年返回 `true`,否則返回 `false`
#### 功能代碼
```javascript
function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
}
```
#### 使用方法
```javascript
sinma.isLeapYear(2024); // true (能被4整除,不能被100整除)
sinma.isLeapYear(2000); // true (能被400整除)
sinma.isLeapYear(1900); // false (能被100整除,不能被400整除)
sinma.isLeapYear(2023); // false (不能被4整除)
```
#### 使用范例
```javascript
// 日歷生成
function getDaysInMonth(year, month) {
const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if (month === 2 && sinma.isLeapYear(year)) {
return 29;
}
return daysInMonth[month - 1];
}
// 年份信息
function getYearInfo(year) {
return {
year: year,
isLeap: sinma.isLeapYear(year),
daysInYear: sinma.isLeapYear(year) ? 366 : 365,
daysInFebruary: sinma.isLeapYear(year) ? 29 : 28
};
}
console.log(getYearInfo(2024));
// { year: 2024, isLeap: true, daysInYear: 366, daysInFebruary: 29 }
// 生日驗(yàn)證
function validateBirthday(dateStr) {
const [year, month, day] = dateStr.split('-').map(Number);
if (month < 1 || month > 12) {
return { valid: false, error: '月份無效' };
}
const maxDays = getDaysInMonth(year, month);
if (day < 1 || day > maxDays) {
return { valid: false, error: `${year}年${month}月只有${maxDays}天` };
}
return { valid: true };
}
// 閏年列表生成
function getLeapYears(startYear, endYear) {
const leapYears = [];
for (let year = startYear; year <= endYear; year++) {
if (sinma.isLeapYear(year)) {
leapYears.push(year);
}
}
return leapYears;
}
console.log(getLeapYears(2020, 2030));
// [2020, 2024, 2028]
```
---
### now(format) - 獲取當(dāng)前時(shí)間
獲取當(dāng)前時(shí)間的格式化字符串。
#### 參數(shù)
- `format` {string} - 格式化模板,默認(rèn) `'YYYY-MM-DD HH:mm:ss'`
#### 返回值
- {string} - 格式化后的當(dāng)前時(shí)間字符串
#### 功能代碼
```javascript
function now(format = 'YYYY-MM-DD HH:mm:ss') {
return this.formatDate(new Date(), format);
}
```
#### 使用方法
```javascript
sinma.now(); // '2023-12-25 14:30:45'
sinma.now('YYYY-MM-DD'); // '2023-12-25'
sinma.now('HH:mm:ss'); // '14:30:45'
sinma.now('YYYY年MM月DD日 HH:mm'); // '2023年12月25日 14:30'
```
#### 使用范例
```javascript
// 日志記錄
function log(level, message) {
const timestamp = sinma.now();
console.log(`[${timestamp}] [${level}] ${message}`);
}
// 數(shù)據(jù)備份
function createBackup(data) {
const filename = `backup_${sinma.now('YYYYMMDD_HHmmss')}.json`;
// 保存數(shù)據(jù)邏輯
return filename;
}
// 會話管理
class Session {
constructor(userId) {
this.userId = userId;
this.createdAt = sinma.now();
this.lastActive = sinma.now();
}
updateActivity() {
this.lastActive = sinma.now();
}
getInfo() {
return {
userId: this.userId,
createdAt: this.createdAt,
lastActive: this.lastActive,
duration: this.calculateDuration()
};
}
calculateDuration() {
const start = sinma.getTimestamp(this.createdAt);
const end = sinma.getTimestamp(this.lastActive);
const diffMs = end - start;
const diffMinutes = Math.floor(diffMs / (1000 * 60));
return `${diffMinutes}分鐘`;
}
}
// API響應(yīng)時(shí)間戳
function apiResponse(data) {
return {
data: data,
timestamp: sinma.now(),
serverTime: sinma.getTimestamp(new Date())
};
}
// 定時(shí)任務(wù)標(biāo)記
function scheduleTask(taskName, intervalMinutes) {
console.log(`任務(wù) ${taskName} 開始執(zhí)行: ${sinma.now()}`);
setInterval(() => {
console.log(`任務(wù) ${taskName} 執(zhí)行中: ${sinma.now()}`);
// 執(zhí)行具體任務(wù)
}, intervalMinutes * 60 * 1000);
}
```
## 高級用法示例
### 日期區(qū)間處理
```javascript
// 日期區(qū)間工具類
class DateRange {
constructor(startDate, endDate) {
this.startDate = new Date(startDate);
this.endDate = new Date(endDate);
}
// 獲取區(qū)間天數(shù)
getDays() {
const diffTime = this.endDate - this.startDate;
return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
}
// 檢查日期是否在區(qū)間內(nèi)
contains(date) {
const checkDate = new Date(date);
return checkDate >= this.startDate && checkDate <= this.endDate;
}
// 獲取區(qū)間內(nèi)所有日期
getAllDates() {
const dates = [];
const current = new Date(this.startDate);
while (current <= this.endDate) {
dates.push(sinma.formatDate(current));
current.setDate(current.getDate() + 1);
}
return dates;
}
// 格式化顯示
toString() {
return `${sinma.formatDate(this.startDate)} 至 ${sinma.formatDate(this.endDate)}`;
}
}
const range = new DateRange('2023-12-01', '2023-12-07');
console.log(range.toString()); // '2023-12-01 至 2023-12-07'
console.log(range.getDays()); // 7
```
### 工作日計(jì)算
```javascript
// 工作日計(jì)算工具
function calculateWorkdays(startDate, endDate, holidays = []) {
const start = new Date(startDate);
const end = new Date(endDate);
const holidaySet = new Set(holidays.map(h => sinma.formatDate(h)));
let workdays = 0;
const current = new Date(start);
while (current <= end) {
const dayOfWeek = current.getDay();
const currentDateStr = sinma.formatDate(current);
// 不是周末且不是節(jié)假日
if (dayOfWeek !== 0 && dayOfWeek !== 6 && !holidaySet.has(currentDateStr)) {
workdays++;
}
current.setDate(current.getDate() + 1);
}
return workdays;
}
// 項(xiàng)目工期計(jì)算
function calculateProjectDuration(startDate, workdaysNeeded) {
const holidays = ['2023-12-25', '2024-01-01']; // 節(jié)假日
let current = new Date(startDate);
let remainingDays = workdaysNeeded;
while (remainingDays > 0) {
const dayOfWeek = current.getDay();
const currentDateStr = sinma.formatDate(current);
if (dayOfWeek !== 0 && dayOfWeek !== 6 && !holidays.includes(currentDateStr)) {
remainingDays--;
}
if (remainingDays > 0) {
current.setDate(current.getDate() + 1);
}
}
return sinma.formatDate(current);
}
```
### 時(shí)間段統(tǒng)計(jì)
```javascript
// 時(shí)間段統(tǒng)計(jì)工具
function analyzeTimeDistribution(timestamps) {
const distribution = {
morning: 0, // 06:00-12:00
afternoon: 0, // 12:00-18:00
evening: 0, // 18:00-22:00
night: 0 // 22:00-06:00
};
timestamps.forEach(timestamp => {
const date = new Date(timestamp);
const hour = date.getHours();
if (hour >= 6 && hour < 12) distribution.morning++;
else if (hour >= 12 && hour < 18) distribution.afternoon++;
else if (hour >= 18 && hour < 22) distribution.evening++;
else distribution.night++;
});
const total = timestamps.length;
return {
counts: distribution,
percentages: {
morning: `${Math.round(distribution.morning / total * 100)}%`,
afternoon: `${Math.round(distribution.afternoon / total * 100)}%`,
evening: `${Math.round(distribution.evening / total * 100)}%`,
night: `${Math.round(distribution.night / total * 100)}%`
}
};
}
```
## 性能優(yōu)化建議
1. **緩存計(jì)算結(jié)果**: 對于重復(fù)的日期計(jì)算,考慮緩存結(jié)果
2. **批量處理**: 大量日期數(shù)據(jù)處理時(shí)使用批量函數(shù)
3. **時(shí)區(qū)處理**: 根據(jù)需要選擇是否考慮時(shí)區(qū)問題
4. **日期驗(yàn)證**: 在處理用戶輸入時(shí)添加日期有效性驗(yàn)證
## 注意事項(xiàng)
1. **時(shí)區(qū)問題**: 默認(rèn)使用本地時(shí)區(qū),跨時(shí)區(qū)應(yīng)用需要特別處理
2. **日期格式**: 輸入的日期字符串格式要符合JavaScript Date構(gòu)造函數(shù)的要求
3. **年份范圍**: JavaScript Date對象的年份范圍限制(1970-2038年問題)
4. **閏秒**: 不考慮閏秒的影響
## 相關(guān)模塊
- [字符串模塊](./string.md) - 提供日期字符串格式化功能
- [數(shù)字模塊](./number.md) - 提供時(shí)間戳數(shù)值計(jì)算功能
- [中文處理模塊](./chinese.md) - 提供從身份證提取生日等功能
