aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDevin Teske <dteske@FreeBSD.org>2026-08-16 03:17:13 +0000
committerDevin Teske <dteske@FreeBSD.org>2026-08-16 03:17:13 +0000
commit8cfe06ee4415795cc77934fb5c17bdf2c2fd3816 (patch)
tree3c0f856e18925a7d79e61fb1a6d1fa5a9f81ae28
parent5e6c894510fc66c18d69164d591184a2d23b16e5 (diff)
bsdconfig: add datetime module for live system clock
Provide bsdconfig datetime (menu), date, and time to set the running system clock via dialog(1)/bsddialog(1) --calendar and --timebox with mustberoot. Unlike bsdinstall's time helper, this operates on the live system rather than a CHROOT-staged install target, and calls adjkerntz(8) after a successful change so the CMOS stays in sync. Reviewed by: bcr Differential Revision: https://reviews.freebsd.org/D58487
-rw-r--r--usr.sbin/bsdconfig/Makefile1
-rw-r--r--usr.sbin/bsdconfig/bsdconfig.810
-rw-r--r--usr.sbin/bsdconfig/datetime/INDEX57
-rw-r--r--usr.sbin/bsdconfig/datetime/Makefile9
-rw-r--r--usr.sbin/bsdconfig/datetime/Makefile.depend10
-rw-r--r--usr.sbin/bsdconfig/datetime/Makefile.inc1
-rw-r--r--usr.sbin/bsdconfig/datetime/USAGE36
-rwxr-xr-xusr.sbin/bsdconfig/datetime/date73
-rwxr-xr-xusr.sbin/bsdconfig/datetime/datetime154
-rw-r--r--usr.sbin/bsdconfig/datetime/include/Makefile4
-rw-r--r--usr.sbin/bsdconfig/datetime/include/datetime.hlp19
-rw-r--r--usr.sbin/bsdconfig/datetime/include/messages.subr41
-rw-r--r--usr.sbin/bsdconfig/datetime/share/Makefile4
-rw-r--r--usr.sbin/bsdconfig/datetime/share/datetime.subr142
-rwxr-xr-xusr.sbin/bsdconfig/datetime/time73
15 files changed, 632 insertions, 2 deletions
diff --git a/usr.sbin/bsdconfig/Makefile b/usr.sbin/bsdconfig/Makefile
index a3b72d248a14..d308c90557ef 100644
--- a/usr.sbin/bsdconfig/Makefile
+++ b/usr.sbin/bsdconfig/Makefile
@@ -3,6 +3,7 @@
PACKAGE= bsdconfig
SUBDIR= console \
+ datetime \
diskmgmt \
docsinstall \
dot \
diff --git a/usr.sbin/bsdconfig/bsdconfig.8 b/usr.sbin/bsdconfig/bsdconfig.8
index aa81785a3acc..0ad74a2e3b2f 100644
--- a/usr.sbin/bsdconfig/bsdconfig.8
+++ b/usr.sbin/bsdconfig/bsdconfig.8
@@ -1,5 +1,5 @@
.\" Copyright (c) 2012 Ron McDowell
-.\" Copyright (c) 2012-2013 Devin Teske
+.\" Copyright (c) 2012-2026 Devin Teske
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -23,7 +23,7 @@
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd June 9, 2026
+.Dd July 27, 2026
.Dt BSDCONFIG 8
.Os
.Sh NAME
@@ -95,6 +95,10 @@ listing.
.Bl -tag -width ".Cm syscons_screenmap"
.It Cm console
Utilities to customize the behavior of the system console.
+.It Cm date
+Set the system date, preserving the current time-of-day.
+.It Cm datetime
+Set the system date and/or time on the running machine.
.It Cm defaultrouter
Shortcut to the Default Router/Gateway menu under networking.
.It Cm diskmgmt
@@ -207,6 +211,8 @@ Shortcut to the Screenmap menu under console for
.It Cm vt_ttys
Shortcut to the Ttys menu under console for
.Xr vt 4 .
+.It Cm time
+Set the system time-of-day, preserving the current calendar date.
.It Cm timezone
Set the regional timezone of the local machine.
.It Cm ttys
diff --git a/usr.sbin/bsdconfig/datetime/INDEX b/usr.sbin/bsdconfig/datetime/INDEX
new file mode 100644
index 000000000000..9f85e68bdc85
--- /dev/null
+++ b/usr.sbin/bsdconfig/datetime/INDEX
@@ -0,0 +1,57 @@
+# Copyright (c) 2026 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+#
+# Title that will be shown in the bsdconfig menu.
+#
+menu_title="Date / Time"
+
+#
+# A short descriptive line shown at the bottom of the bsdconfig menu. keep it
+# short because any line longer than the terminal width will be truncated.
+#
+menu_help="Set the system date and/or time"
+
+#
+# Two-part variable that defines an action to take when `keyword' is passed on
+# a bsdconfig command line. Variable takes the form "keyword|command" and
+# multiple occurrences of the variable (with different `keyword's, or different
+# `keyword's AND `command's) are allowed. If `command' begins with a '/' then
+# the full path to the program is needed. If `command' begins with anything
+# else it is a path relative to the directory this INDEX file is in. `keyword'
+# can be i18n'ed but `command' is the name of a script.
+#
+menu_selection="datetime|datetime"
+menu_selection="date|date"
+menu_selection="time|time"
+
+#
+# ------------ Items below this line do NOT need i18n translation ------------
+#
+# Name of the program to be run when this menu choice is selected. If it begins
+# with a '/' then the full path to the program is needed. If it begins with
+# anything else it is a path relative to the directory this INDEX file is in.
+#
+menu_program="datetime"
diff --git a/usr.sbin/bsdconfig/datetime/Makefile b/usr.sbin/bsdconfig/datetime/Makefile
new file mode 100644
index 000000000000..600340a075c0
--- /dev/null
+++ b/usr.sbin/bsdconfig/datetime/Makefile
@@ -0,0 +1,9 @@
+SUBDIR= include share
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/085.datetime
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= date datetime time
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/bsdconfig/datetime/Makefile.depend b/usr.sbin/bsdconfig/datetime/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.sbin/bsdconfig/datetime/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.sbin/bsdconfig/datetime/Makefile.inc b/usr.sbin/bsdconfig/datetime/Makefile.inc
new file mode 100644
index 000000000000..01b5f23410c8
--- /dev/null
+++ b/usr.sbin/bsdconfig/datetime/Makefile.inc
@@ -0,0 +1 @@
+.include "../Makefile.inc"
diff --git a/usr.sbin/bsdconfig/datetime/USAGE b/usr.sbin/bsdconfig/datetime/USAGE
new file mode 100644
index 000000000000..cb2fdc733853
--- /dev/null
+++ b/usr.sbin/bsdconfig/datetime/USAGE
@@ -0,0 +1,36 @@
+# Copyright (c) 2026 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+ -d Provide lots of debugging info on standard-out when running.
+ -D file Send debugging info to file. If file begins with a plus-sign
+ debug info is sent to both standard-out and file (minus the
+ leading plus).
+ -h Print this usage statement and exit.
+ -S Secure X11 mode (implies `-X'). As root, always prompt-for
+ and validate sudo(8) username/password before starting.
+ -X Use Xdialog(1) in place of dialog(1).
diff --git a/usr.sbin/bsdconfig/datetime/date b/usr.sbin/bsdconfig/datetime/date
new file mode 100755
index 000000000000..dde5be929090
--- /dev/null
+++ b/usr.sbin/bsdconfig/datetime/date
@@ -0,0 +1,73 @@
+#!/bin/sh
+#-
+# Copyright (c) 2026 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/datetime/datetime.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="085.datetime"
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_set_date"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Set the system date (Cancel/ESC leaves the clock unchanged)
+#
+f_dialog_calendar_set_date
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/usr.sbin/bsdconfig/datetime/datetime b/usr.sbin/bsdconfig/datetime/datetime
new file mode 100755
index 000000000000..5f42d79278f6
--- /dev/null
+++ b/usr.sbin/bsdconfig/datetime/datetime
@@ -0,0 +1,154 @@
+#!/bin/sh
+#-
+# Copyright (c) 2026 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="085.datetime"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+DATETIME_HELPFILE=$BSDCFG_LIBE/$APP_DIR/include/datetime.hlp
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt=
+ local menu_list="
+ 'D' '$msg_date'
+ 'T' '$msg_time'
+ 'X' '$msg_exit'
+ " # END-QUOTE
+ local defaultitem= # Calculated below
+ local hline="$hline_arrows_tab_enter"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ # Obtain default-item from previously stored selection
+ f_dialog_default_fetch defaultitem
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --help-button \
+ --help-label \"\$msg_help\" \
+ ${USE_XDIALOG:+--help \"\"} \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+
+ # Only update default-item on success
+ [ $retval -eq $DIALOG_OK ] && f_dialog_default_store "$menu_choice"
+
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_date_time"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+ dialog_menu_main
+ retval=$?
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+
+ if [ $retval -eq $DIALOG_HELP ]; then
+ f_show_help "$DATETIME_HELPFILE"
+ continue
+ elif [ $retval -ne $DIALOG_OK ]; then
+ f_die
+ fi
+
+ command=
+ case "$mtag" in
+ X) break ;;
+ D) command=date ;; # Set Date
+ T) command=time ;; # Set Time
+ esac
+
+ if [ "$command" ]; then
+ $BSDCFG_LIBE/$APP_DIR/$command ${USE_XDIALOG:+-X}
+ else
+ f_die 1 "$msg_unknown_date_time_menu_selection"
+ fi
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/usr.sbin/bsdconfig/datetime/include/Makefile b/usr.sbin/bsdconfig/datetime/include/Makefile
new file mode 100644
index 000000000000..da1d4daaa5c0
--- /dev/null
+++ b/usr.sbin/bsdconfig/datetime/include/Makefile
@@ -0,0 +1,4 @@
+FILESDIR= ${LIBEXECDIR}/bsdconfig/085.datetime/include
+FILES= messages.subr datetime.hlp
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/bsdconfig/datetime/include/datetime.hlp b/usr.sbin/bsdconfig/datetime/include/datetime.hlp
new file mode 100644
index 000000000000..7b0b0ed7c023
--- /dev/null
+++ b/usr.sbin/bsdconfig/datetime/include/datetime.hlp
@@ -0,0 +1,19 @@
+These screens allow you to set the system date and time on the
+running system.
+
+Date
+====
+
+Choose Date to open a calendar pre-filled with the current local
+date. Confirming applies that calendar day while preserving the
+current time-of-day.
+
+Time
+====
+
+Choose Time to open a time box pre-filled with the current local
+time. Confirming applies that time-of-day while preserving the
+current calendar date.
+
+Timezone is configured separately (bsdconfig timezone). Setting
+the clock here does not change which zone /etc/localtime names.
diff --git a/usr.sbin/bsdconfig/datetime/include/messages.subr b/usr.sbin/bsdconfig/datetime/include/messages.subr
new file mode 100644
index 000000000000..55e40553c403
--- /dev/null
+++ b/usr.sbin/bsdconfig/datetime/include/messages.subr
@@ -0,0 +1,41 @@
+# Copyright (c) 2026 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+hline_arrows_tab_enter="Press arrows, TAB or ENTER"
+msg_cancel="Cancel"
+msg_date="Date"
+msg_date_time="Date / Time"
+msg_error="ERROR!"
+msg_exit="Exit"
+msg_help="Help"
+msg_ok="OK"
+msg_set_date="Set Date"
+msg_set_time="Set Time"
+msg_system_date_set="System date set to:\n\n%s"
+msg_system_time_set="System time set to:\n\n%s"
+msg_time="Time"
+msg_unable_to_set_date="Unable to set the system date."
+msg_unable_to_set_time="Unable to set the system time."
+msg_unknown_date_time_menu_selection="Unknown date/time menu selection"
diff --git a/usr.sbin/bsdconfig/datetime/share/Makefile b/usr.sbin/bsdconfig/datetime/share/Makefile
new file mode 100644
index 000000000000..dbf9035a2c73
--- /dev/null
+++ b/usr.sbin/bsdconfig/datetime/share/Makefile
@@ -0,0 +1,4 @@
+FILESDIR= ${SHAREDIR}/bsdconfig/datetime
+FILES= datetime.subr
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/bsdconfig/datetime/share/datetime.subr b/usr.sbin/bsdconfig/datetime/share/datetime.subr
new file mode 100644
index 000000000000..8c016ade9b7c
--- /dev/null
+++ b/usr.sbin/bsdconfig/datetime/share/datetime.subr
@@ -0,0 +1,142 @@
+if [ ! "$_DATETIME_DATETIME_SUBR" ]; then _DATETIME_DATETIME_SUBR=1
+#
+# Copyright (c) 2026 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." datetime/datetime.subr
+f_include $BSDCFG_SHARE/dialog.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="085.datetime"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ FUNCTIONS
+
+# f_datetime_adjkerntz
+#
+# Best-effort CMOS sync after changing the system clock with date(1).
+#
+f_datetime_adjkerntz()
+{
+ f_quietly adjkerntz -a
+}
+
+# f_dialog_calendar_set_date
+#
+# Prompt with dialog(1) --calendar and set the system date, preserving the
+# current time-of-day. Returns dialog status (Cancel/ESC) without dying.
+#
+f_dialog_calendar_set_date()
+{
+ local prompt="$msg_set_date"
+ local hline="$hline_arrows_tab_enter"
+ local cheight cwidth input_date ret_date retval
+ local cur_tod setstr
+
+ f_dialog_calendar_size cheight cwidth \
+ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$prompt" "$hline"
+
+ input_date=$( date "+%d %m %Y" )
+ ret_date=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --calendar \"\$prompt\" \
+ $cheight $cwidth \
+ $input_date \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ retval=$?
+ f_dialog_data_sanitize ret_date
+ f_dprintf "retval=%u ret_date=[%s]" $retval "$ret_date"
+ [ $retval -eq $DIALOG_OK ] || return $retval
+
+ cur_tod=$( date "+%H:%M:%S" )
+ setstr=$( date -j -f "%d/%m/%Y %T" -- \
+ "$ret_date $cur_tod" "+%Y%m%d%H%M.%S" ) ||
+ f_die 1 "$msg_unable_to_set_date"
+
+ f_eval_catch "$0" date 'date "%s"' "$setstr" ||
+ f_die 1 "$msg_unable_to_set_date"
+ f_datetime_adjkerntz
+ f_show_msg "$msg_system_date_set" "$( date )"
+ return $SUCCESS
+}
+
+# f_dialog_timebox_set_time
+#
+# Prompt with dialog(1) --timebox and set the system time, preserving the
+# current calendar date. Returns dialog status (Cancel/ESC) without dying.
+#
+f_dialog_timebox_set_time()
+{
+ local prompt="$msg_set_time"
+ local hline="$hline_arrows_tab_enter"
+ local input_time ret_time retval
+ local cur_day setstr
+
+ #
+ # bsddialog(1) --timebox wants total rows (min 7), not dialog(1)-style
+ # text height. Match bsdinstall time: autosize height, width 40.
+ #
+ input_time=$( date "+%H %M %S" )
+ ret_time=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --timebox \"\$prompt\" \
+ 0 40 \
+ $input_time \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ retval=$?
+ f_dialog_data_sanitize ret_time
+ f_dprintf "retval=%u ret_time=[%s]" $retval "$ret_time"
+ [ $retval -eq $DIALOG_OK ] || return $retval
+
+ cur_day=$( date "+%d/%m/%Y" )
+ setstr=$( date -j -f "%d/%m/%Y %T" -- \
+ "$cur_day $ret_time" "+%Y%m%d%H%M.%S" ) ||
+ f_die 1 "$msg_unable_to_set_time"
+
+ f_eval_catch "$0" date 'date "%s"' "$setstr" ||
+ f_die 1 "$msg_unable_to_set_time"
+ f_datetime_adjkerntz
+ f_show_msg "$msg_system_time_set" "$( date )"
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." datetime/datetime.subr
+
+fi # ! $_DATETIME_DATETIME_SUBR
diff --git a/usr.sbin/bsdconfig/datetime/time b/usr.sbin/bsdconfig/datetime/time
new file mode 100755
index 000000000000..908d756b0d8a
--- /dev/null
+++ b/usr.sbin/bsdconfig/datetime/time
@@ -0,0 +1,73 @@
+#!/bin/sh
+#-
+# Copyright (c) 2026 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/datetime/datetime.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="085.datetime"
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_set_time"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Set the system time (Cancel/ESC leaves the clock unchanged)
+#
+f_dialog_timebox_set_time
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################