天天看點

NodeJS 擷取指定時區的時間

/**
 * 擷取指定時區的時間
 * @param offset 時區
 * @returns {Date} 指定時區的 時間資訊
 */
module.exports.getZoneTime = (offset)=> {
    // 取本地時間
    let localtime = new Date();
    // 取本地毫秒數
    let localmesc = localtime.getTime();
    // 取本地時區與格林尼治所在時區的偏差毫秒數
    let localOffset = localtime.getTimezoneOffset() * ;
    // 反推得到格林尼治時間
    let utc = localOffset + localmesc;
    // 得到指定時區時間
    let calctime = utc + ( * offset);
    return new Date(calctime);
};
           

帶驗證 方法 參考Java實作

/**
 * 檢查時區 函數  錯誤時區就傳回+0000
 * @param tz 時區 參考JAVA實作方法
 */
module.exports.checkTz = (tz) => {
    if (!tz) {
        tz = "+0000";
    }
    if ('-' != tz.charAt() && '+' != tz.charAt()) {
        tz = "+" + tz;
    }
    let hours, minutes, seconds;
    switch (tz.length) {
        case :
            tz = tz.charAt() + "0" + tz.charAt();
        case :
            hours = parseNumber(tz, , false);
            minutes = ;
            seconds = ;
            break;
        case :
            hours = parseNumber(tz, , false);
            minutes = parseNumber(tz, , false);
            seconds = ;
            break;
        case :
            hours = parseNumber(tz, , false);
            minutes = parseNumber(tz, , true);
            seconds = ;
            break;
        case :
            hours = parseNumber(tz, , false);
            minutes = parseNumber(tz, , false);
            seconds = parseNumber(tz, , false);
            break;
        case :
            hours = parseNumber(tz, , false);
            minutes = parseNumber(tz, , true);
            seconds = parseNumber(tz, , true);
            break;
        default:
            throw new Error("Invalid ID for ZoneOffset, invalid format: " + tz);
    }
    let first = tz.charAt();
    if (first != '+' && first != '-') {
        throw new Error("Invalid ID for ZoneOffset, plus/minus not found when expected: " + tz);
    }
    if (first == '-') {
        return ofHoursMinutesSeconds(-hours, -minutes, -seconds);
    } else {
        return ofHoursMinutesSeconds(hours, minutes, seconds);
    }
};
/**
 * 解析 數字
 * @param tz 時區
 * @param pos 起始位置
 * @param precededByColon 是否有:
 * @returns {number} 解析後的結果
 */
function parseNumber(tz, pos, precededByColon) {
    if (precededByColon && tz.charAt(pos - ) != ":") {//檢驗 格式為:+08:00
        throw new Error("Invalid ID for ZoneOffset, colon not found when expected: " + tz);
    }
    let ch1 = tz.charCodeAt(pos);
    let ch2 = tz.charCodeAt(pos + );
    if (String.fromCharCode(ch1) < "0" || String.fromCharCode(ch1) > "9" ||
        String.fromCharCode(ch2) < "0" || String.fromCharCode(ch2) > "9") {
        throw new Error("Invalid ID for ZoneOffset, non numeric characters found: " + tz);
    }
    return (ch1 - ) *  + (ch2 - );
}

function ofHoursMinutesSeconds(hours, minutes, seconds) {
    validate(hours, minutes, seconds);
    let totalS = totalSeconds(hours, minutes, seconds);
    return ofTotalSeconds(totalS);
}

function ofTotalSeconds(totalS) {
    // 取本地時間
    let localtime = new Date();
    // 取本地毫秒數
    let localmesc = localtime.getTime();
    // 取本地時區與格林尼治所在時區的偏差毫秒數
    let localOffset = localtime.getTimezoneOffset() * ;
    // 反推得到格林尼治時間
    let utc = localOffset + localmesc;
    // 得到指定時區時間
    let calctime = utc + (totalS*);
    return new Date(calctime);
}

/**
 * 計算秒數
 * @param hours 小時
 * @param minutes 分鐘
 * @param seconds 秒
 * @returns {*} 總共多少秒
 */
function totalSeconds(hours, minutes, seconds) {
    return hours * SECONDS_PER_HOUR + minutes * SECONDS_PER_MINUTE + seconds;
}

/**
 * Validates the offset fields.
 *  驗證時間偏移量字段
 * @param hours   in hours, from -18 to +18
 * @param minutes   in minutes, from 0 to &plusmn;59
 * @param seconds   in seconds, from 0 to &plusmn;59
 * @throws Error if the offset is not in the required range
 */
function validate(hours, minutes, seconds) {
    if (hours < - || hours > ) {
        throw new Error("Zone offset hours not in valid range: value " + hours +
            " is not in the range -18 to 18");
    }
    if (hours > ) {
        if (minutes <  || seconds < ) {
            throw new Error("Zone offset minutes and seconds must be positive because hours is positive");
        }
    } else if (hours < ) {
        if (minutes >  || seconds > ) {
            throw new Error("Zone offset minutes and seconds must be negative because hours is negative");
        }
    } else if ((minutes >  && seconds < ) || (minutes <  && seconds > )) {
        throw new Error("Zone offset minutes and seconds must have the same sign");
    }
    if (Math.abs(minutes) > ) {
        throw new Error("Zone offset minutes not in valid range: abs(value) " +
            Math.abs(minutes) + " is not in the range 0 to 59");
    }
    if (Math.abs(seconds) > ) {
        throw new Error("Zone offset seconds not in valid range: abs(value) " +
            Math.abs(seconds) + " is not in the range 0 to 59");
    }
    if (Math.abs(hours) ==  && (Math.abs(minutes) >  || Math.abs(seconds) > )) {
        throw new Error("Zone offset not in valid range: -18:00 to +18:00");
    }
}