はじめに
システムやアプリケーションのテストで、特定の日付での動作を確認したい場合がある。datefudgeは、実際のシステム日付を変更せずに、特定のプロセスが認識する日付だけを偽装できるコマンドである。
時刻関連のテストやレガシーシステムの動作確認、期限切れ証明書のテストなどに便利である。
環境
Ubuntu 24.04 LTS
datefudge 1.26datefudgeのインストール
sudo apt update
sudo apt install datefudgeログ
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following packages were automatically installed and are no longer required:
crack-common gyp libcares2 libgl1-amber-dri libglapi-mesa libjs-async libjs-events libjs-inherits
libjs-is-typedarray libjs-prettify libjs-regenerate libjs-source-map libjs-sprintf-js
libjs-typedarray-to-buffer libllvm17t64 liblttng-ust-common1t64 liblttng-ust-ctl5t64 liblttng-ust1t64
libnotify-bin libqt5x11extras5 libre2-10 libssl-dev libuv1-dev libxcb-damage0 mesa-utils-bin node-abbrev
node-ampproject-remapping node-ansi-regex node-ansi-styles node-aproba node-are-we-there-yet node-arrify
node-async node-async-each node-auto-bind node-babel-plugin-add-module-exports node-babel7-runtime
node-balanced-match node-base64-js node-binary-extensions node-brace-expansion node-busboy
node-camelcase node-caniuse-lite node-chownr node-chrome-trace-event node-ci-info node-cjs-module-lexer
node-cli-boxes node-cli-cursor node-clone node-collection-visit node-color-convert node-color-name
node-colors node-commander node-commondir node-concat-stream node-console-control-strings
node-convert-source-map node-core-js node-core-js-pure node-core-util-is node-data-uri-to-buffer
node-decompress-response node-deep-is node-defaults node-define-property node-delegates node-depd
node-diff node-electron-to-chromium node-encoding node-end-of-stream node-err-code node-error-ex
node-es-module-lexer node-escape-string-regexp node-eslint-utils node-eslint-visitor-keys node-esquery
node-estraverse node-esutils node-events node-fancy-log node-fast-deep-equal node-fast-levenshtein
node-fetch node-find-up node-flatted node-foreground-child node-fs-readdir-recursive
node-fs-write-stream-atomic node-fs.realpath node-function-bind node-get-caller-file node-get-stream
node-get-value node-glob node-globals node-got node-graceful-fs node-growl node-has-flag
node-has-unicode node-has-value node-has-values node-hosted-git-info node-iconv-lite node-ieee754
node-iferr node-imurmurhash node-indent-string node-inflight node-inherits node-ini node-interpret
node-ip node-ip-regex node-is-arrayish node-is-binary-path node-is-buffer node-is-descriptor
node-is-extglob node-is-path-cwd node-is-plain-obj node-is-plain-object node-is-stream
node-is-typedarray node-is-windows node-isarray node-isexe node-isobject node-js-tokens node-json-buffer
node-json-parse-better-errors node-json-schema node-json-schema-traverse node-json-stable-stringify
node-jsonify node-jsonparse node-kind-of node-levn node-loader-runner node-locate-path
node-lodash-packages node-lowercase-keys node-lru-cache node-map-visit node-memfs node-merge-stream
node-mimic-response node-minimatch node-minimist node-minipass node-mute-stream node-n3 node-negotiator
node-npm-run-path node-object-inspect node-object-visit node-once node-optimist node-optionator
node-osenv node-p-cancelable node-p-limit node-p-locate node-p-map node-pascalcase node-path-dirname
node-path-exists node-path-is-absolute node-path-is-inside node-path-type node-pify node-pkg-dir
node-postcss-value-parser node-prelude-ls node-process-nextick-args node-promise-inflight
node-promise-retry node-promzard node-prr node-pump node-punycode node-quick-lru node-randombytes
node-read node-readable-stream node-rechoir node-regenerator-runtime node-regenerator-transform
node-regexpp node-regjsgen node-repeat-string node-require-directory node-require-from-string
node-resolve node-resolve-cwd node-resolve-from node-restore-cursor node-resumer node-retry
node-run-queue node-safe-buffer node-serialize-javascript node-set-blocking node-set-immediate-shim
node-shebang-command node-shebang-regex node-shell-quote node-signal-exit node-slash node-slice-ansi
node-source-list-map node-source-map node-spdx-correct node-spdx-exceptions node-spdx-expression-parse
node-spdx-license-ids node-sprintf-js node-ssri node-stack-utils node-string-decoder node-strip-bom
node-supports-color node-tapable node-terser node-text-table node-through node-time-stamp
node-to-fast-properties node-tslib node-type-check node-typedarray node-typedarray-to-buffer node-undici
node-unicode-canonical-property-names-ecmascript node-unicode-match-property-value-ecmascript
node-unicode-property-aliases-ecmascript node-unset-value node-uri-js node-util-deprecate node-uuid
node-v8flags node-validate-npm-package-license node-wcwidth.js node-webpack-sources node-wordwrap
node-wrappy node-write-file-atomic node-xtend node-y18n node-yallist node-yaml nodejs-doc xbitmaps
Use 'sudo apt autoremove' to remove them.
The following NEW packages will be installed:
datefudge
0 upgraded, 1 newly installed, 0 to remove and 31 not upgraded.
Need to get 8350 B of archives.
After this operation, 35.8 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu noble/universe amd64 datefudge amd64 1.26 [8350 B]
Fetched 8350 B in 1s (7893 B/s)
Selecting previously unselected package datefudge:amd64.
(Reading database ... 116728 files and directories currently installed.)
Preparing to unpack .../datefudge_1.26_amd64.deb ...
Unpacking datefudge:amd64 (1.26) ...
Setting up datefudge:amd64 (1.26) ...
Processing triggers for man-db (2.12.0-4build2) ...インストール後、ヘルプを確認する。
datefudge --versiondatefudge --version
/usr/bin/datefudge: Version 1.26
For usage information, use '/usr/bin/datefudge --help'.datefudgeを使う
基本的な使い方
datefudgeの基本的な構文は以下の通り。
datefudge <偽装したい日付> <実行するコマンド> [コマンドの引数...]例:
# dateコマンドを2020年1月1日として実行
datefudge "2020-01-01" date
# dateコマンドを2023年12月31日として実行
datefudge "2023-12-31" date
# Pythonスクリプトを特定の日付で実行
datefudge "2022-06-15" python3 script.py
# 現在の日付と偽装した日付の比較
echo "現在の日付:" && date && echo "偽装した日付:" && datefudge "2023-12-31" dateこの場合、指定したコマンド(date、python3など)とその子プロセスのみが偽装された日付を認識する。
日付の指定方法
日付は複数の形式で指定できる。
# YYYY-MM-DD形式(dateコマンドが偽装された日付で実行される)
datefudge "2020-01-01" date
# YYYY-MM-DD HH:MM:SS形式(dateコマンドが偽装された日付で実行される)
datefudge "2020-12-31 23:59:59" date
# MM/DD/YYYY形式も可能(dateコマンドが偽装された日付で実行される)
datefudge "12/31/2023" date
# 曜日と時刻を含む形式(dateコマンドが偽装された日付で実行される)
datefudge "Wed Jan 1 00:00:00 UTC 2020" date上記の例では、datefudgeの後に指定した日付でdateコマンドが実行される。
重要: 偽装されるのはdatefudgeコマンドの引数として指定したプロセス(上記の例ではdateコマンド)とその子プロセスのみ。システム全体の日付は変更されない。
実際に使ってみる
現在の日付と偽装した日付の比較
実際にdatefudgeの効果を確認してみる。
echo "現在の日付:" && date && echo "偽装した日付:" && datefudge "2023-12-31" dateecho "現在の日付:" && date && echo "偽装した日付:" && datefudge "2023-12-31" date
現在の日付:
Sun Sep 7 01:14:16 JST 2025
偽装した日付:
Sun Dec 31 00:00:00 JST 2023このように、datefudgeで指定したコマンドのみが偽装された日付で実行されていることがわかる。
特定の日付を指定して実行
datefudge "2020-01-01" dateWed Jan 1 00:00:00 UTC 2020実際のシステム日付は変更されていないことを確認。
dateSat Sep 6 04:06:48 PM UTC 2025複数コマンドの実行
シェルを起動して複数コマンドを実行する場合。
datefudge "2022-06-15" bashこの状態でシェル内で実行するコマンドは全て2022年6月15日として認識される。
date ~ datefudge "2022-06-15" bash
kbushi@kbushi:~$ date
Wed Jun 15 00:00:04 JST 2022スクリプトファイルの実行
日付を偽装してスクリプトを実行する例。
# テスト用スクリプトの作成
cat << 'EOF' > test_date.sh
#!/bin/bash
echo "現在の日付: $(date)"
echo "エポック秒: $(date +%s)"
echo "年: $(date +%Y)"
echo "月: $(date +%m)"
echo "日: $(date +%d)"
EOF
chmod +x test_date.sh通常実行。
./test_date.sh現在の日付: Sun Sep 7 01:17:14 JST 2025
エポック秒: 1757175434
年: 2025
月: 09
日: 07datefudgeで日付を偽装して実行。
datefudge "2000-01-01" ./test_date.sh現在の日付: Sat Jan 1 00:00:00 JST 2000
エポック秒: 946652400
年: 2000
月: 01
日: 01ファイルのタイムスタンプテスト
注意: datefudgeはファイルの変更時刻(modification times)は変更しない。ファイルのタイムスタンプは実際のシステム時刻で記録される。
# 過去の日付でファイルを作成してみる(実際には現在の日付で作成される)
datefudge "1999-12-31" touch old_file.txt
# 現在の日付でファイルを作成
touch current_file.txt
# タイムスタンプを比較
ls -la *_file.txt-rw-r--r-- 1 vscode vscode 0 Sep 6 16:18 old_file.txt
-rw-r--r-- 1 vscode vscode 0 Sep 6 16:18 current_file.txtこのように、どちらのファイルも同じ現在の日付で作成されている。datefudgeではtouchコマンドでファイルのタイムスタンプを偽装することはできない。
ファイルのタイムスタンプも偽装したい場合は、libfaketimeパッケージのfaketimeコマンドを使用する必要がある。
プログラムの期限テスト
期限切れや有効期限のテストに使用する例。
# Python スクリプトの例
cat << 'EOF' > check_expiry.py
#!/usr/bin/env python3
import datetime
expiry_date = datetime.date(2024, 12, 31)
today = datetime.date.today()
print(f"今日の日付: {today}")
print(f"期限日: {expiry_date}")
if today > expiry_date:
print("期限切れです!")
exit(1)
else:
print("まだ有効です")
exit(0)
EOF
chmod +x check_expiry.py通常実行(2025年なので期限切れ)。
./check_expiry.py今日の日付: 2025-09-07
期限日: 2024-12-31
期限切れです!2024年として実行(有効)。
datefudge "2024-06-15" ./check_expiry.py今日の日付: 2024-06-15
期限日: 2024-12-31
まだ有効です注意点
1. システム全体には影響しない
datefudgeは指定したプロセスとその子プロセスにのみ影響する。システム全体の日付は変更されない。
2. 一部のアプリケーションでは効果がない
ハードウェアクロックを直接参照するアプリケーションや、特別な時刻取得方法を使用するアプリケーションでは効果がない場合がある。
3. ネットワーク関連の注意
NTPクライアントやネットワーク経由で時刻を取得するアプリケーションには影響しない。
4. ファイル変更時刻について
manページの「BUGS」セクションでは以下のように明記されている:
There is no attempt to make this change undetectable by the program. In particular, file modification times are not modified.
datefudgeはファイルの変更時刻(modification times)は変更しない。この機能が必要な場合は、libfaketimeパッケージのfaketimeコマンドを検討する。
5. 2038年問題の影響
manページでも2038年問題について言及されている:
On systems using 32-bit representation of time, datefudge is affected by the year 2038 problem, which might cause dates to be wrapped around, for instance:
32ビットシステムでは2038年問題の影響を受ける可能性がある。
# 例:2038年1月19日以降で予期しない動作が発生する可能性
TZ=UTC datefudge "2038-01-19 03:14:07" sh -c "sleep 1; date -R"
# 結果が1901年になってしまう場合がある(manページの例)
# Fri Dec 13 20:45:53 UTC 19016. –add-ld-preload オプションについて
manページには以下のオプションが記載されている
–add-ld-preload lib, -l lib
Prepend lib to LD_PRELOAD environment variable before executing given program. This option might be useful for example to inject sanitizer libraries (e.g. from Address Sanitizer) to the list of preloaded libraries before the internal datefudge’s library.
通常は自動的に処理されるが、特定の環境(Address Sanitizerなど)では明示的な指定が必要になることがある。
7. タイムゾーンについて
デフォルトではUTCで動作する。ローカルタイムゾーンを使用したい場合は環境変数TZを設定する。
TZ="Asia/Tokyo" datefudge "2024-01-01 09:00:00" date関連コマンドとの比較
faketime との比較
libfaketimeのfaketimeコマンドも同様の機能を提供する。
# datefudge
datefudge "2020-01-01" date
# faketime
faketime '2020-01-01' date| 項目 | datefudge | faketime |
|---|---|---|
| 軽量性 | シンプルで軽量 | より多機能だが重い |
| 日付偽装 | 基本的な日付偽装に特化 | より高機能な日付偽装 |
| ファイル変更時刻 | 変更しない | 偽装可能 |
| 制御オプション | 基本的なオプションのみ | 細かい制御オプションが豊富 |
| 適用場面 | シンプルな日付テスト | より複雑なテストシナリオ |
| パッケージ | datefudge | libfaketime |
manページでも、ファイル変更時刻について以下のように記載されている:
BUGS
There is no attempt to make this change undetectable by the program. In particular, file modification times are not modified.
(翻訳:このプログラムによる変更を検出不可能にする試みはない。特に、ファイルの変更時刻は変更されない。)
このため、ファイル変更時刻の偽装が必要な場合はfaketimeの使用が推奨されている。
参考
datefudge - Debian Package Repository
https://packages.debian.org/stable/datefudgedatefudge - Ubuntu Package Repository
https://packages.ubuntu.com/noble/devel/datefudgelibfaketime - GitHub
https://github.com/wolfcw/libfaketimeシステム時刻を偽装するツールの比較
https://wiki.debian.org/FakeTimepackagesの説明文書を訳しつつ、使えるものを探してみました(D編)
https://blog.geeko.jp/ribbon/2822
おわりに
datefudgeは、システム日付を変更せずに特定のプロセスの認識する日付だけを偽装できる便利なツールである。
時刻に依存するシステムのテストや、過去・未来の日付での動作確認に重宝する。
システム全体に影響を与えずにテストできるのが利点である。
バックアップスクリプトの動作確認や、期限切れ処理のテスト、年末年始の特別処理のテストなど、様々な場面で活用できるコマンドだと思った。