2016年10月25日 星期二

日期加減、星期

活用setXXX和getXXX即可,連潤年也都可以解決,以下還加上民國年的轉換
但檢核沒什麼判斷

※日期加減(使用API)

window.onload = function(){
    mingoDateStringAddSubstract('105/10/30', '/', 'm', -2);
    mingoDateStringAddSubstract('1051030', '', 'm', -2);
}
    
/*
    mingoDateString:民國年月日字串
    split:要分割的符號,可以為空
    ymd:要針對年、月、日作用
    number:加減年、月、日數
*/
function mingoDateStringAddSubstract(mingoDateString, split, ymd, number){
    if(mingoDateString.length != 7 && mingoDateString.length != 9){
        return 'yyymmdd or yyy?mm?dd';
    }
    
    var year, month, date;
    split = split.trim();
    if(split != ''){
        var dateArray = mingoDateString.split(split);
        year = dateArray[0];
        month = dateArray[1];
        date = dateArray[2];
    } else {
        year = mingoDateString.substring(0, 3);
        month = mingoDateString.substring(3, 5);
        date = mingoDateString.substring(5);
    }
    
    // 月-1是因為月是從0開始
    var d = new Date(Number(year) + 1911, Number(month) - 1, date);
    console.log('before=' + d.toDateString());
    if('y' == ymd.toLowerCase()){
        d.setYear(d.getFullYear() + number);
    } else if('m' == ymd.toLowerCase()){
        d.setMonth(d.getMonth() + number);
    } else if('d' == ymd.toLowerCase()){
        d.setDate(d.getDate() + number);
    }
    console.log('after=' + d.toDateString());
    
    // 轉民國年,月+1是因為月是從0開始
    var rtnYear = Number(d.getFullYear()) - 1911;
    var rtnMonth = Number(d.getMonth()) + 1;
    var rtnDate = d.getDate();
    
    if(year.length == 2){
        year = '0' + year;
    } else if(year.length == 1){
        year = '00' + year;
    }
    rtnMonth = rtnMonth < 10 ? '0' + rtnMonth : rtnMonth;
    rtnDate = rtnDate < 10 ? '0' + rtnDate : rtnDate;
    
    console.log(rtnYear + split + rtnMonth + split + rtnDate);
    console.log('==========');
}



※日期加減(不用API)

window.onload = function(){
    console.log(mingoDateCalc('105/10/30', '/', 'm', -2));
    console.log(mingoDateCalc('1051030', '', 'm', -2));
}
    
// 是否閏年
function isLeapYear(year){
    /* 網路上找到的閏年判斷邏輯  
    4的倍數-->非100的倍數-->閏
           -->  100的倍數-->非400的倍數-->非閏
                         -->  400的倍數-->閏
    y/4 == 0 && y/100 != 0 
    y/4 == 0 && y/100 == 0 && y/400 == 0 
    
    */
    
    /*
    if(
        (year % 4 == 0 && year % 100 != 0) || 
        (year % 4 == 0 && year % 100 == 0 && year % 400 == 0)
    ){
        return true;
    } else {
        return false;
    }
    */
    
    // 簡化後
    if(year % 4 == 0){
        if(year % 100 != 0){
            return true;
        } else {
            return year % 400 == 0 ? true : false;
        }
    } else {
        return false;
    }
}
    
// 回傳當月天數
function judgeDateOfMonth(year, month){
    switch(month) {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            return 31
            break;
        case 4:
        case 6:
        case 9:
        case 11:
            return 30
            break;
        default:
            if(isLeapYear(Number(year) + 1911)){
                return 29;
            } else {
                return 28;
            }
    }
}
    
function mingoDateCalc(mingoDateString, split, ymd, number){
    if(mingoDateString.length != 7 && mingoDateString.length != 9){
        return 'yyymmdd or yyy?mm?dd';
    }
    
    var year, month, date;
    split = split.trim();
    if(split != ''){
        var dateArray = mingoDateString.split(split);
        year = Number(dateArray[0]);
        month = Number(dateArray[1]);
        date = Number(dateArray[2]);
    } else {
        year = Number(mingoDateString.substring(0, 3));
        month = Number(mingoDateString.substring(3, 5));
        date = Number(mingoDateString.substring(5));
    }
    
    if(ymd == 'y'){
        year = year + number;
        if(month == 2 && date == 29){
            // 非潤年,加1或減1看需求而定(API是加1)
            if(number > 0 && !isLeapYear(Number(year) + 1911)){
                // 減1
                //date = date - 1;
    
                // 加1
                month = 3;
                date = 1;
            }
        }
    } else if(ymd == 'm'){
        if(number > 0) {
            year = year + Math.floor(number / 12);
            month = month + (number % 12);
            if(month > 12){
                year = year + 1;
                month = month - 12;
            }
        } else {
            number = Math.abs(number);
            year = year - Math.floor(number / 12);
            month = month - (number % 12);
            if(month <= 0){
                year = year - 1;
                month = month + 12;
            }
        }
    } else if(ymd == 'd'){
        if(number > 0) {
            date = date + number;
            var ymdArray = calcPlusDate(year, month, date);
            year = ymdArray[0];
            month = ymdArray[1];
            date = ymdArray[2];
        } else {
            date = date + number;
    
            // 一開始要判斷上個月的天數,所以先扣一個月
            month = month - 1;
            if(month == 0){
                year = year - 1;
                month = 12;
            }
            var ymdArray = calcMinusDate(year, month, date);
            year = ymdArray[0];
            month = ymdArray[1];
            date = ymdArray[2];
        }
    }
    
    if(year.length == 2){
        year = '0' + year;
    } else if(year.length == 1){
        year = '00' + year;
    }
    month = month < 10 ? '0' + month : month;
    date = date < 10 ? '0' + date : date;
    return year + split + month + split + date;
}
    
// 計算天數為正
function calcPlusDate(y, m, d){
    var day = judgeDateOfMonth(y, m);
    if(d > day){
        d = d - day;
        m = m + 1;
        if(m == 13){
            y = y + 1;
            m = 1;
        }
        return calcPlusDate(y, m, d);
    }
    return new Array(y, m, d);
}
    
// 計算天數為負
function calcMinusDate(y, m, d){
    var day = judgeDateOfMonth(y, m);
    if(d < 0){
        d = d + day;
        m = m - 1;
        if(m == 0){
            y = y - 1;
            m = 12;
        }
        return calcMinusDate(y, m, d);
    }
    
    // 一開始先扣了一個月,這裡要加回來
    m = m + 1;
    if(m == 13){
        y = y + 1;
        m = 1;
    }
    return new Array(y, m, d);
}

※雖然沒有測很仔細,但應該和API一樣

※檢核可用正則表達式加強一下



※星期

※API有getDay()可取得星期,自己寫的話就要設定一個寫死的日期是星期幾,然後根據這一個來判斷,如下:

window.onload = function(){
    var y = 2011; var m = 11; var d = 30;
    
    // 兩個日期相差的天數,使用new Date API
    var d1 = new Date(2012, 1 - 1, 1);//月減1是因為API是從0開始
    var d2 = new Date(y, m - 1, d);
    var oneDay = 60 * 60 * 24;
    console.log('用API算相差的天數=' + Math.abs((d1-d2) / (oneDay * 1000)));
    
    apiWeek(y, m, d);
    noApiWeek(y, m, d);
}
    
function apiWeek(year, month, date) {
    // 使用API
    // 月-1是因為月是從0開始
    var d = new Date(year, month - 1, date);
    console.log('用API算出的日期=' + d.getDay());// 0為星期日
}
    
function noApiWeek(year, month, date) {
    // 不使用API
    // 2012/1/1 星期日
    // 2010 12 13 星期一
    var baseYear = 2012;
    var baseMonth = 1;
    var totalDay = 0;
    
    //月日一定>=1,所以不用判斷
    if(year >= baseYear){
        totalDay = date;
        while(true){
            if(baseMonth > 12){
                baseYear = baseYear + 1;
                baseMonth = baseMonth - 12;
            }
    
            if(baseYear == year && baseMonth == month){
                break;
            }
    
            totalDay = totalDay + judgeDateOfMonth(baseYear, baseMonth);
            baseMonth = baseMonth + 1;
        }
        totalDay = Math.abs(totalDay - 1);
        console.log('不用API算相差的天數=' + totalDay);
        getPositiveWeek(totalDay % 7);
    } else {
        // 判斷上個月的日期
        baseMonth = 12;
        baseYear = 2011;
    
        var lastMonthDay = judgeDateOfMonth(baseYear, baseMonth);
        totalDay = Math.abs(lastMonthDay - date + 1); 
    
        while(true){
            if(baseYear == year && baseMonth == month){
                break;
            }
    
            baseMonth = baseMonth - 1;
            if(baseMonth == 0){
                baseYear = baseYear - 1;
                baseMonth = 12;
            }
            totalDay = totalDay + judgeDateOfMonth(baseYear, baseMonth);
        }
        console.log('不用API算相差的天數=' + totalDay);
        getNegativeWeek(totalDay % 7);
    }
}
    
// 是否閏年
function isLeapYear(year){
    if(year % 4 == 0){
        if(year % 100 != 0){
            return true;
        } else {
            return year % 400 == 0 ? true : false;
        }
    } else {
        return false;
    }
}
    
function getPositiveWeek(weekNumber){
    var display = '不用API算出的日期=星期';
    switch(weekNumber) {
        case 0:
            console.log(display + '日');
            break;
        case 1:
            console.log(display + '一');
            break;
        case 2:
            console.log(display + '二');
            break;
        case 3:
            console.log(display + '三');
            break;
        case 4:
            console.log(display + '四');
            break;
        case 5:
            console.log(display + '五');
            break;
        case 6:
            console.log(display + '六');
            break;
    }
}
    
function getNegativeWeek(weekNumber){
    var display = '不用API算出的日期=星期';
    switch(weekNumber) {
        case 0:
            console.log(display + '日');
            break;
        case 1:
            console.log(display + '六');
            break;
        case 2:
            console.log(display + '五');
            break;
        case 3:
            console.log(display + '四');
            break;
        case 4:
            console.log(display + '三');
            break;
        case 5:
            console.log(display + '二');
            break;
        case 6:
            console.log(display + '一');
            break;
    }
}
    
// 回傳當月天數
function judgeDateOfMonth(year, month){
    switch(month) {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            return 31
            break;
        case 4:
        case 6:
        case 9:
        case 11:
            return 30
            break;
        default:
            if(isLeapYear(year)){
                return 29;
            } else {
                return 28;
            }
    }
}

※已2012/1/1為基準,我故意選星期天為0的,因為這樣比這個日期大的日期,結果會和API一樣

※回傳當月天數和日期加減的程式碼稍有不同,因為不用民國年了,所以將+1911拿掉了

沒有留言:

張貼留言