GAS×日付操作|日付計算と書式設定の完全ガイド
GASで日付を扱おうとして、スプレッドシートから取得した値が意味不明な数字になった経験はないだろうか。あるいは日付の表示形式を変えたい、営業日だけカウントしたい、といった場面に遭遇したことがあるかもしれない。
GASの日付操作はJavaScriptのDateオブジェクトがベースになっている。月が0始まりだったり、タイムゾーンの罠があったりと、独特のクセがある。ただ、基本パターンを押さえれば日付計算もフォーマット変換も難しくない。
GASでの日付の扱い方(Dateオブジェクト)
GASではJavaScriptのDateオブジェクトを使って日付を扱う。
Dateオブジェクトの基本
function dateBasics() {
// 現在日時を取得
const now = new Date();
console.log('現在:', now); // Mon Feb 02 2026 15:30:00 GMT+0900 (JST)
// Dateオブジェクトは「日時」を表す
// → 年、月、日、時、分、秒、ミリ秒を持つ
}
月は0始まり ── 最大の落とし穴
function monthWarning() {
// ⚠️ 月は 0〜11 で表される(1月=0, 12月=11)
const date = new Date(2026, 1, 15); // 2026年2月15日(1ではなく2月!)
console.log(date);
// 分かりやすくするコツ
const year = 2026;
const month = 2 - 1; // 2月 → 1 と書く
const day = 15;
const date2 = new Date(year, month, day);
}
new Date(2026, 1, 15) は2月15日を指す。1月のつもりで書くと1ヶ月ずれる。この仕様は何年経っても間違えやすいので、2 - 1 のように意図を明示する書き方をおすすめする。
日付の作成・取得方法
日付の作成パターン
function createDates() {
// パターン1: 現在日時
const now = new Date();
// パターン2: 年月日を指定(時刻は00:00:00)
const date1 = new Date(2026, 1, 15); // 2026年2月15日
// パターン3: 年月日時分秒を指定
const date2 = new Date(2026, 1, 15, 10, 30, 0); // 2026年2月15日 10:30:00
// パターン4: 文字列から作成
const date3 = new Date('2026-02-15'); // ISO形式
const date4 = new Date('2026/02/15'); // スラッシュ区切り
const date5 = new Date('February 15, 2026'); // 英語形式
// パターン5: タイムスタンプ(ミリ秒)から作成
const timestamp = 1771113600000;
const date6 = new Date(timestamp);
}
日付の各要素を取得
function getDateParts() {
const date = new Date(2026, 1, 15, 10, 30, 45);
console.log('年:', date.getFullYear()); // 2026
console.log('月:', date.getMonth()); // 1(2月)※0始まり
console.log('月(実際):', date.getMonth() + 1); // 2
console.log('日:', date.getDate()); // 15
console.log('曜日:', date.getDay()); // 0(日曜)〜6(土曜)
console.log('時:', date.getHours()); // 10
console.log('分:', date.getMinutes()); // 30
console.log('秒:', date.getSeconds()); // 45
console.log('ミリ秒:', date.getMilliseconds()); // 0
console.log('タイムスタンプ:', date.getTime()); // ミリ秒
}
曜日の変換
function getDayName() {
const date = new Date();
const dayIndex = date.getDay(); // 0〜6
// 日本語の曜日
const dayNamesJa = ['日', '月', '火', '水', '木', '金', '土'];
console.log('曜日:', dayNamesJa[dayIndex]);
// 英語の曜日
const dayNamesEn = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
console.log('Day:', dayNamesEn[dayIndex]);
}
日付の加算・減算
基本: setXxx() メソッドを使う
function addSubtractDates() {
// === 日を加算・減算 ===
const date = new Date(2026, 1, 15); // 2026年2月15日
// 7日後
date.setDate(date.getDate() + 7);
console.log('7日後:', date); // 2026年2月22日
// 10日前
date.setDate(date.getDate() - 10);
console.log('10日前:', date); // 2026年2月12日
// === 月を加算・減算 ===
const date2 = new Date(2026, 1, 15);
// 3ヶ月後
date2.setMonth(date2.getMonth() + 3);
console.log('3ヶ月後:', date2); // 2026年5月15日
// === 年を加算・減算 ===
const date3 = new Date(2026, 1, 15);
// 1年後
date3.setFullYear(date3.getFullYear() + 1);
console.log('1年後:', date3); // 2027年2月15日
}
注意: 元の日付が変わる
function dateModificationWarning() {
const original = new Date(2026, 1, 15);
// ⚠️ setDate() は元のオブジェクトを変更する
original.setDate(original.getDate() + 7);
console.log(original); // 2026年2月22日(元の日付が変わった!)
// ✅ 元の日付を保持したい場合は、コピーを作る
const original2 = new Date(2026, 1, 15);
const newDate = new Date(original2); // コピーを作成
newDate.setDate(newDate.getDate() + 7);
console.log('元の日付:', original2); // 2026年2月15日(変わらない)
console.log('新しい日付:', newDate); // 2026年2月22日
}
setDate() は破壊的メソッドで、呼び出し元のオブジェクトを直接書き換える。元の日付を残したい場合は new Date(original) でコピーしてから操作すること。
便利関数: 日付の加算
/**
* 日付を加算する(元の日付は変更しない)
* @param {Date} date - 基準日
* @param {number} days - 加算する日数(負の値で減算)
* @return {Date} - 新しい日付
*/
function addDays(date, days) {
const result = new Date(date);
result.setDate(result.getDate() + days);
return result;
}
/**
* 月を加算する
*/
function addMonths(date, months) {
const result = new Date(date);
result.setMonth(result.getMonth() + months);
return result;
}
/**
* 年を加算する
*/
function addYears(date, years) {
const result = new Date(date);
result.setFullYear(result.getFullYear() + years);
return result;
}
// 使用例
function testAddFunctions() {
const today = new Date();
console.log('今日:', today);
console.log('7日後:', addDays(today, 7));
console.log('3日前:', addDays(today, -3));
console.log('1ヶ月後:', addMonths(today, 1));
console.log('1年後:', addYears(today, 1));
}
日数の差を計算
/**
* 2つの日付の差(日数)を計算
*/
function daysBetween(date1, date2) {
const oneDay = 24 * 60 * 60 * 1000; // 1日のミリ秒
const diff = Math.abs(date2 - date1);
return Math.floor(diff / oneDay);
}
function testDaysBetween() {
const start = new Date(2026, 1, 1); // 2026年2月1日
const end = new Date(2026, 1, 15); // 2026年2月15日
console.log('日数差:', daysBetween(start, end), '日'); // 14日
}
日付のフォーマット(Utilities.formatDate)
GASには日付をフォーマットする専用関数 Utilities.formatDate() がある。
基本構文
Utilities.formatDate(date, timeZone, format)
| 引数 | 説明 | 例 |
|---|---|---|
date |
フォーマットする日付 | new Date() |
timeZone |
タイムゾーン | 'Asia/Tokyo' |
format |
フォーマット文字列 | 'yyyy/MM/dd' |
フォーマット文字一覧
| 文字 | 意味 | 出力例 |
|---|---|---|
yyyy |
年(4桁) | 2026 |
yy |
年(2桁) | 26 |
MM |
月(2桁、ゼロ埋め) | 02 |
M |
月(ゼロ埋めなし) | 2 |
dd |
日(2桁、ゼロ埋め) | 05 |
d |
日(ゼロ埋めなし) | 5 |
HH |
時(24時間、2桁) | 14 |
H |
時(24時間) | 14 |
hh |
時(12時間、2桁) | 02 |
mm |
分(2桁) | 05 |
ss |
秒(2桁) | 09 |
E |
曜日(短縮) | Mon |
EEEE |
曜日(フル) | Monday |
a |
午前/午後 | AM / PM |
よく使うフォーマット例
function formatExamples() {
const date = new Date(2026, 1, 5, 14, 30, 0); // 2026年2月5日 14:30:00
const tz = 'Asia/Tokyo';
// 基本形式
console.log(Utilities.formatDate(date, tz, 'yyyy/MM/dd'));
// → 2026/02/05
console.log(Utilities.formatDate(date, tz, 'yyyy-MM-dd'));
// → 2026-02-05
console.log(Utilities.formatDate(date, tz, 'yyyy年MM月dd日'));
// → 2026年02月05日
console.log(Utilities.formatDate(date, tz, 'yyyy年M月d日'));
// → 2026年2月5日(ゼロ埋めなし)
// 時刻付き
console.log(Utilities.formatDate(date, tz, 'yyyy/MM/dd HH:mm:ss'));
// → 2026/02/05 14:30:00
console.log(Utilities.formatDate(date, tz, 'yyyy/MM/dd HH:mm'));
// → 2026/02/05 14:30
// 曜日付き
console.log(Utilities.formatDate(date, tz, 'yyyy/MM/dd (E)'));
// → 2026/02/05 (Thu)
console.log(Utilities.formatDate(date, tz, 'M月d日(E)'));
// → 2月5日(Thu)
// 時刻のみ
console.log(Utilities.formatDate(date, tz, 'HH:mm'));
// → 14:30
// ISO 8601形式
console.log(Utilities.formatDate(date, tz, "yyyy-MM-dd'T'HH:mm:ss"));
// → 2026-02-05T14:30:00
}
日本語の曜日を表示
Utilities.formatDate() の曜日出力は英語表記になる。日本語で表示するには別のアプローチが必要だ。
/**
* 日本語の曜日付きでフォーマット
*/
function formatDateJapanese(date) {
const tz = 'Asia/Tokyo';
const dayNames = ['日', '月', '火', '水', '木', '金', '土'];
const dayName = dayNames[date.getDay()];
const formatted = Utilities.formatDate(date, tz, 'yyyy年M月d日');
return `${formatted}(${dayName})`;
}
function testJapaneseFormat() {
const date = new Date(2026, 1, 5);
console.log(formatDateJapanese(date)); // 2026年2月5日(木)
}
実践例1 営業日計算
土日祝を除いた営業日を計算する。請求書の支払期限や納品日の算出に使える。
/**
* 営業日を加算する(土日除く)
* @param {Date} startDate - 開始日
* @param {number} businessDays - 加算する営業日数
* @return {Date} - 営業日後の日付
*/
function addBusinessDays(startDate, businessDays) {
const result = new Date(startDate);
let count = 0;
while (count < businessDays) {
result.setDate(result.getDate() + 1);
const dayOfWeek = result.getDay();
// 土曜(6)と日曜(0)をスキップ
if (dayOfWeek !== 0 && dayOfWeek !== 6) {
count++;
}
}
return result;
}
/**
* 営業日を加算する(土日祝除く)
* @param {Date} startDate - 開始日
* @param {number} businessDays - 加算する営業日数
* @param {Date[]} holidays - 祝日の配列(オプション)
* @return {Date} - 営業日後の日付
*/
function addBusinessDaysWithHolidays(startDate, businessDays, holidays = []) {
const result = new Date(startDate);
let count = 0;
// 祝日を比較用の文字列に変換
const holidayStrings = holidays.map(h =>
Utilities.formatDate(h, 'Asia/Tokyo', 'yyyy-MM-dd')
);
while (count < businessDays) {
result.setDate(result.getDate() + 1);
const dayOfWeek = result.getDay();
const dateString = Utilities.formatDate(result, 'Asia/Tokyo', 'yyyy-MM-dd');
// 土日と祝日をスキップ
const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
const isHoliday = holidayStrings.includes(dateString);
if (!isWeekend && !isHoliday) {
count++;
}
}
return result;
}
/**
* 使用例: 3営業日後を計算
*/
function testBusinessDays() {
const today = new Date();
const tz = 'Asia/Tokyo';
// 土日のみ除外
const result1 = addBusinessDays(today, 3);
console.log('3営業日後(土日除く):', Utilities.formatDate(result1, tz, 'yyyy/MM/dd (E)'));
// 祝日も除外
const holidays = [
new Date(2026, 1, 11), // 建国記念の日
new Date(2026, 1, 23), // 天皇誕生日
];
const result2 = addBusinessDaysWithHolidays(today, 3, holidays);
console.log('3営業日後(祝日含む):', Utilities.formatDate(result2, tz, 'yyyy/MM/dd (E)'));
}
2つの日付間の営業日数を計算
/**
* 2つの日付間の営業日数を計算
*/
function countBusinessDays(startDate, endDate) {
let count = 0;
const current = new Date(startDate);
while (current <= endDate) {
const dayOfWeek = current.getDay();
if (dayOfWeek !== 0 && dayOfWeek !== 6) {
count++;
}
current.setDate(current.getDate() + 1);
}
return count;
}
function testCountBusinessDays() {
const start = new Date(2026, 1, 1); // 2026年2月1日(日)
const end = new Date(2026, 1, 28); // 2026年2月28日(土)
console.log('営業日数:', countBusinessDays(start, end), '日');
}
実践例2 期限チェック・リマインダー
スプレッドシートに記録されたタスクの期限をチェックし、期限が近いものをメールで通知するスクリプトだ。
/**
* 期限が近いタスクをチェックしてリマインド
* スプレッドシート形式: A列=タスク名, B列=期限日, C列=担当者メール
*/
function checkDeadlines() {
const sheet = SpreadsheetApp.getActiveSheet();
const data = sheet.getDataRange().getValues();
const today = new Date();
const tz = 'Asia/Tokyo';
// 今日の0時0分に正規化(時刻を無視して日付だけ比較)
today.setHours(0, 0, 0, 0);
const alerts = [];
for (let i = 1; i < data.length; i++) {
const taskName = data[i][0];
const deadline = new Date(data[i][1]);
const email = data[i][2];
if (!taskName || !deadline) continue;
// 期限日を0時0分に正規化
deadline.setHours(0, 0, 0, 0);
// 日数差を計算
const diffDays = Math.floor((deadline - today) / (24 * 60 * 60 * 1000));
// 期限が3日以内または過ぎている場合にアラート
if (diffDays <= 3) {
let status;
if (diffDays < 0) {
status = `⚠️ ${Math.abs(diffDays)}日超過`;
} else if (diffDays === 0) {
status = '🔴 本日期限';
} else {
status = `🟡 あと${diffDays}日`;
}
alerts.push({
task: taskName,
deadline: Utilities.formatDate(deadline, tz, 'M月d日'),
email: email,
status: status,
diffDays: diffDays
});
}
}
// アラートがあれば通知
if (alerts.length > 0) {
sendDeadlineAlert(alerts);
}
console.log(`チェック完了: ${alerts.length}件のアラート`);
return alerts;
}
/**
* 期限アラートをメール送信
*/
function sendDeadlineAlert(alerts) {
const recipient = Session.getActiveUser().getEmail();
const today = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy年M月d日');
let body = `【期限アラート】${today}\n\n`;
body += `${alerts.length}件のタスクが期限間近または超過しています。\n\n`;
body += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n';
alerts.forEach((alert, index) => {
body += `【${index + 1}】${alert.task}\n`;
body += ` 期限: ${alert.deadline}\n`;
body += ` 状態: ${alert.status}\n\n`;
});
GmailApp.sendEmail(recipient, `【要対応】期限アラート(${alerts.length}件)`, body);
}
月末・月初の判定
/**
* 今日が月末かどうか
*/
function isEndOfMonth(date = new Date()) {
const tomorrow = new Date(date);
tomorrow.setDate(tomorrow.getDate() + 1);
return tomorrow.getDate() === 1;
}
/**
* 今日が月初かどうか
*/
function isStartOfMonth(date = new Date()) {
return date.getDate() === 1;
}
/**
* 月末日を取得
*/
function getEndOfMonth(date) {
const result = new Date(date.getFullYear(), date.getMonth() + 1, 0);
return result;
}
/**
* 月初日を取得
*/
function getStartOfMonth(date) {
return new Date(date.getFullYear(), date.getMonth(), 1);
}
function testMonthBoundaries() {
const today = new Date();
const tz = 'Asia/Tokyo';
console.log('今日は月末?:', isEndOfMonth());
console.log('今日は月初?:', isStartOfMonth());
console.log('今月の月末:', Utilities.formatDate(getEndOfMonth(today), tz, 'yyyy/MM/dd'));
console.log('今月の月初:', Utilities.formatDate(getStartOfMonth(today), tz, 'yyyy/MM/dd'));
}
タイムゾーンの注意点
GASのタイムゾーン問題
GASはデフォルトでUTC(協定世界時)を使う場合があり、日本時間との9時間のズレがバグの原因になりやすい。
function timeZoneIssue() {
const date = new Date('2026-02-15'); // 文字列から作成
// ⚠️ UTCとして解釈される可能性
console.log('そのまま出力:', date);
console.log('時刻:', date.getHours()); // 9(日本時間で0時のはずが9時に)
// ✅ タイムゾーンを明示してフォーマット
console.log('日本時間:', Utilities.formatDate(date, 'Asia/Tokyo', 'yyyy/MM/dd HH:mm'));
}
安全な日付作成方法
/**
* タイムゾーンを考慮した安全な日付作成
*/
function createDateSafely(year, month, day) {
// コンストラクタで直接指定(ローカルタイム)
return new Date(year, month - 1, day); // 月は-1する
}
/**
* 文字列から安全に日付を作成
*/
function parseDateString(dateString) {
// 'yyyy/MM/dd' または 'yyyy-MM-dd' 形式を想定
const parts = dateString.split(/[\/\-]/);
const year = parseInt(parts[0]);
const month = parseInt(parts[1]) - 1; // 月は-1
const day = parseInt(parts[2]);
return new Date(year, month, day);
}
function testSafeDateCreation() {
const tz = 'Asia/Tokyo';
const date1 = createDateSafely(2026, 2, 15); // 2026年2月15日
console.log('安全に作成:', Utilities.formatDate(date1, tz, 'yyyy/MM/dd HH:mm'));
const date2 = parseDateString('2026/02/15');
console.log('文字列から:', Utilities.formatDate(date2, tz, 'yyyy/MM/dd HH:mm'));
}
ISO形式の文字列 '2026-02-15' からDateを生成するとUTCとして解釈される。日本時間で扱いたい場合は new Date(year, month - 1, day) のコンストラクタ形式を使うか、parseDateString() のように文字列を分解してから生成するのが安全だ。
スプレッドシートの日付を正しく取得
function getDateFromSpreadsheet() {
const sheet = SpreadsheetApp.getActiveSheet();
const cell = sheet.getRange('A1');
// getValue()で取得するとDateオブジェクトになる
const dateValue = cell.getValue();
if (dateValue instanceof Date) {
// 正しくDateオブジェクトとして取得できた
const tz = 'Asia/Tokyo';
console.log('取得した日付:', Utilities.formatDate(dateValue, tz, 'yyyy/MM/dd'));
} else {
// 文字列として取得された場合
console.log('文字列として取得:', dateValue);
const parsedDate = parseDateString(String(dateValue));
console.log('パース後:', parsedDate);
}
}
よくあるエラーと対処法
エラー1: Invalid Date
// ❌ エラー: 無効な日付文字列
const date = new Date('2026/2/30'); // 2月30日は存在しない
console.log(date); // Invalid Date
// ✅ 対処: 日付の妥当性チェック
function isValidDate(date) {
return date instanceof Date && !isNaN(date.getTime());
}
const testDate = new Date('2026/2/30');
if (!isValidDate(testDate)) {
console.error('無効な日付です');
}
エラー2: 月のズレ(0始まり問題)
// ❌ 間違い: 2月のつもりが3月になる
const wrong = new Date(2026, 2, 15); // 2026年3月15日!
// ✅ 正しい: 月は-1する
const correct = new Date(2026, 2 - 1, 15); // 2026年2月15日
エラー3: 日付の比較
// ❌ 間違い: 直接比較すると時刻も含まれる
const date1 = new Date(2026, 1, 15, 10, 0, 0);
const date2 = new Date(2026, 1, 15, 14, 0, 0);
console.log(date1 === date2); // false(同じ日だが時刻が違う)
console.log(date1 == date2); // false
// ✅ 正しい: 日付部分だけ比較
function isSameDay(d1, d2) {
return d1.getFullYear() === d2.getFullYear() &&
d1.getMonth() === d2.getMonth() &&
d1.getDate() === d2.getDate();
}
console.log(isSameDay(date1, date2)); // true
// または文字列に変換して比較
const tz = 'Asia/Tokyo';
const str1 = Utilities.formatDate(date1, tz, 'yyyy-MM-dd');
const str2 = Utilities.formatDate(date2, tz, 'yyyy-MM-dd');
console.log(str1 === str2); // true
エラー4: スプレッドシートの日付がシリアル値になる
// スプレッドシートの日付がシリアル値(数値)として取得された場合
function convertSerialToDate(serial) {
// Excelのシリアル値は1900年1月1日を1とする
// ただしGoogleスプレッドシートでは1899年12月30日が基準
const baseDate = new Date(1899, 11, 30);
const result = new Date(baseDate.getTime() + serial * 24 * 60 * 60 * 1000);
return result;
}
function testSerialConversion() {
const serial = 46066; // 2026年2月15日のシリアル値
const date = convertSerialToDate(serial);
console.log('変換結果:', Utilities.formatDate(date, 'Asia/Tokyo', 'yyyy/MM/dd'));
}
まとめ
覚えておくべきポイント
| ポイント | 説明 |
|---|---|
| 月は0始まり | 1月=0, 12月=11 |
| setXxx()は元を変更 | コピーを作ってから操作 |
| フォーマットはUtilities | Utilities.formatDate(date, tz, format) |
| タイムゾーンを明示 | 'Asia/Tokyo' を指定 |
よく使うパターン
// 今日の日付(時刻なし)
const today = new Date();
today.setHours(0, 0, 0, 0);
// 日付のフォーマット
Utilities.formatDate(date, 'Asia/Tokyo', 'yyyy年M月d日');
// N日後
const future = new Date(today);
future.setDate(future.getDate() + 7);
// 日数差
const diff = Math.floor((date2 - date1) / (24 * 60 * 60 * 1000));
次のステップ
- GAS×Googleカレンダー連携 で予定管理を自動化
- GASデバッグ完全ガイド でエラー解決スキルを習得
- GAS×ChatGPT入門 でAI連携を学ぶ
日付操作はGASを書くうえで避けて通れない。月の0始まり、タイムゾーン、破壊的メソッド ── この3つの罠さえ意識しておけば、大半のトラブルは防げる。
最終更新: 2026-02-02
コメント