2015年4月10日金曜日

kintone@日付と日時を比較する方法

●背景
日付と日時を比較した時に問題は起きた。

まずは下図のように日付と日時を並べてみるのである。


そして、両データをJavaScriptでアラート表示させてみるのである。


なんでじゃー。3/31よ、君はどっからきたー。

というわけなのである。
日付の方は入力された通りの正しい日付が入っているように見える、が、
日時の方は一日前の、とんちんかんな時間を指している、ように見える。

●原因
日時はタイムゾーンの影響を受けるようである。
つまり、日時だけは世界標準時で設定されるわけだ。

日本であれば「+9時間の時差がある」とみなされて、
「4/1の0時」からシステムサイドで-9時間の処理を行い、
「3/31の15時」というアラートが出てしまうわけだ。

はー、使いにくい話である。

●対策
「日時の比較」であれば「日付」を-9時間すれば良い。
「日付フォームの値を送るとその地域の時差に合わせて日時が取得できるコード」
をサンプルコードとして作った。


●サンプルコード
    /***************************************************************************************************
    * function getDateTime
    * @param:date:「event['record']['日付']['value']」等をそのまま引き渡す
    ***************************************************************************************************/
    function getDateTime(date) {
        // ログインユーザのタイムゾーン名を取得する。日本なら「Asia/Tokyo」と取得
        var timeZone = kintone.getLoginUser().timezone;
        
        // タイムゾーン名から時差を取得
        var timeZoneOffset = getTimeZoneOffset(timeZone);
        
        // 年月日を抽出
        var dateFromYYYY = event['record']['日付']['value'].substring(0, 4);
        var dateFromMM = event['record']['日付']['value'].substring(5, 7);
        var dateFromDD = event['record']['日付']['value'].substring(8, 10);
        
        // 月(0~11)調整しながら、時差を加味したDateオブジェクトを生成
        var dateFromYMDT = new Date(dateFromYYYY, dateFromMM - 1, dateFromDD, timeZoneOffset, 0);
        
        // Dateオブジェクトから「日時フォーム」形式に整形する
        var dateFromYYYY2 = dateFromYMDT.getFullYear();
        var dateFromMM2 = ('00' + String(dateFromYMDT.getMonth() + 1)).slice(-2);
        var dateFromDD2 = ('00' + dateFromYMDT.getDate()).slice(-2);
        var dateFromHH2 = ('00' + dateFromYMDT.getHours()).slice(-2);
        var dateFromMI2 = ('00' + dateFromYMDT.getMinutes()).slice(-2);
        var dateFromYMDT2 = dateFromYYYY2 + '-' + dateFromMM2 + '-' + dateFromDD2
            + 'T' + dateFromHH2 + ':' + dateFromMI2 + ':' + '00Z';

        return dateFromYMDT2;
    }

    /***************************************************************************************************
    * function getTimeZoneOffset
    * @param:timeZoneName:タイムゾーン名
    ***************************************************************************************************/
    function getTimeZoneOffset(timeZoneName) {
        var ret = -9;
        var timeZoneOffsetObj = new Object();
        timeZoneOffsetObj['Etc/GMT+12'] = 12;
        timeZoneOffsetObj['Etc/GMT+11'] = 11;
        timeZoneOffsetObj['Pacific/Honolulu'] = 10;
        timeZoneOffsetObj['America/Anchorage'] = 9;
        timeZoneOffsetObj['America/Santa_Isabel'] = 8;
        timeZoneOffsetObj['America/Los_Angeles'] = 8;
        timeZoneOffsetObj['America/Chihuahua'] = 7;
        timeZoneOffsetObj['America/Phoenix'] = 7;
        timeZoneOffsetObj['America/Denver'] = 7;
        timeZoneOffsetObj['America/Guatemala'] = 6;
        timeZoneOffsetObj['America/Chicago'] = 6;
        timeZoneOffsetObj['America/Regina'] = 6;
        timeZoneOffsetObj['America/Mexico_City'] = 6;
        timeZoneOffsetObj['America/Bogota'] = 5;
        timeZoneOffsetObj['America/Indiana/Indianapolis'] = 5;
        timeZoneOffsetObj['America/New_York'] = 5;
        timeZoneOffsetObj['America/Caracas'] = 4.5;
        timeZoneOffsetObj['America/Halifax'] = 4;
        timeZoneOffsetObj['America/Asuncion'] = 4;
        timeZoneOffsetObj['America/La_Paz'] = 4;
        timeZoneOffsetObj['America/Cuiaba'] = 4;
        timeZoneOffsetObj['America/Santiago'] = 4;
        timeZoneOffsetObj['America/St_Johns'] = 3.5;
        timeZoneOffsetObj['America/Sao_Paulo'] = 3;
        timeZoneOffsetObj['America/Godthab'] = 3;
        timeZoneOffsetObj['America/Cayenne'] = 3;
        timeZoneOffsetObj['America/Argentina/Buenos_Aires'] = 3;
        timeZoneOffsetObj['America/Montevideo'] = 3;
        timeZoneOffsetObj['Etc/GMT2'] = 2;
        timeZoneOffsetObj['Atlantic/Cape_Verde'] = 1;
        timeZoneOffsetObj['Atlantic/Azores'] = 1;
        timeZoneOffsetObj['Africa/Casablanca'] = -0;
        timeZoneOffsetObj['Atlantic/Reykjavik'] = -0;
        timeZoneOffsetObj['Europe/London'] = -0;
        timeZoneOffsetObj['Etc/GMT'] = -0;
        timeZoneOffsetObj['Europe/Berlin'] = -1;
        timeZoneOffsetObj['Europe/Paris'] = -1;
        timeZoneOffsetObj['Africa/Lagos'] = -1;
        timeZoneOffsetObj['Europe/Budapest'] = -1;
        timeZoneOffsetObj['Europe/Warsaw'] = -1;
        timeZoneOffsetObj['Africa/Windhoek'] = -1;
        timeZoneOffsetObj['Europe/Istanbul'] = -2;
        timeZoneOffsetObj['Europe/Kiev'] = -2;
        timeZoneOffsetObj['Africa/Cairo'] = -2;
        timeZoneOffsetObj['Asia/Damascus'] = -2;
        timeZoneOffsetObj['Asia/Amman'] = -2;
        timeZoneOffsetObj['Africa/Johannesburg'] = -2;
        timeZoneOffsetObj['Asia/Jerusalem'] = -2;
        timeZoneOffsetObj['Asia/Beirut'] = -2;
        timeZoneOffsetObj['Asia/Baghdad'] = -3;
        timeZoneOffsetObj['Europe/Minsk'] = -3;
        timeZoneOffsetObj['Asia/Riyadh'] = -3;
        timeZoneOffsetObj['Africa/Nairobi'] = -3;
        timeZoneOffsetObj['Asia/Tehran'] = -3.5;
        timeZoneOffsetObj['Europe/Moscow'] = -4;
        timeZoneOffsetObj['Asia/Tbilisi'] = -4;
        timeZoneOffsetObj['Asia/Yerevan'] = -4;
        timeZoneOffsetObj['Asia/Dubai'] = -4;
        timeZoneOffsetObj['Asia/Baku'] = -4;
        timeZoneOffsetObj['Indian/Mauritius'] = -4;
        timeZoneOffsetObj['Asia/Kabul'] = -4.5;
        timeZoneOffsetObj['Asia/Tashkent'] = -5;
        timeZoneOffsetObj['Asia/Karachi'] = -5;
        timeZoneOffsetObj['Asia/Colombo'] = -5.5;
        timeZoneOffsetObj['Asia/Kolkata'] = -5.5;
        timeZoneOffsetObj['Asia/Kathmandu'] = -5.75;
        timeZoneOffsetObj['Asia/Almaty'] = -6;
        timeZoneOffsetObj['Asia/Dhaka'] = -6;
        timeZoneOffsetObj['Asia/Yekaterinburg'] = -6;
        timeZoneOffsetObj['Asia/Rangoon'] = -6.5;
        timeZoneOffsetObj['Asia/Bangkok'] = -7;
        timeZoneOffsetObj['Asia/Novosibirsk'] = -7;
        timeZoneOffsetObj['Asia/Krasnoyarsk'] = -8;
        timeZoneOffsetObj['Asia/Ulaanbaatar'] = -8;
        timeZoneOffsetObj['Asia/Shanghai'] = -8;
        timeZoneOffsetObj['Australia/Perth'] = -8;
        timeZoneOffsetObj['Asia/Singapore'] = -8;
        timeZoneOffsetObj['Asia/Taipei'] = -8;
        timeZoneOffsetObj['Asia/Irkutsk'] = -9;
        timeZoneOffsetObj['Asia/Seoul'] = -9;
        timeZoneOffsetObj['Asia/Tokyo'] = -9;
        timeZoneOffsetObj['Australia/Darwin'] = -9.5;
        timeZoneOffsetObj['Australia/Adelaide'] = -9.5;
        timeZoneOffsetObj['Australia/Hobart'] = -10;
        timeZoneOffsetObj['Asia/Yakutsk'] = -10;
        timeZoneOffsetObj['Australia/Brisbane'] = -10;
        timeZoneOffsetObj['Pacific/Port_Moresby'] = -10;
        timeZoneOffsetObj['Australia/Sydney'] = -10;
        timeZoneOffsetObj['Asia/Vladivostok'] = -11;
        timeZoneOffsetObj['Pacific/Guadalcanal'] = -11;
        timeZoneOffsetObj['Etc/GMT-12'] = -12;
        timeZoneOffsetObj['Pacific/Fiji'] = -12;
        timeZoneOffsetObj['Asia/Magadan'] = -12;
        timeZoneOffsetObj['Pacific/Auckland'] = -12;
        timeZoneOffsetObj['Pacific/Tongatapu'] = -13;
        timeZoneOffsetObj['Pacific/Apia'] = -13;
        for (var key in timeZoneOffsetObj) {
            if (key == timeZoneName) {
                ret = timeZoneOffsetObj[key];
                break;
            }
        }
        return ret;
    }

0 件のコメント:

コメントを投稿