Rabu, 21 Oktober 2026
04:35 WIB
TERKINI
Pemprov Lampung Kolaborasi Pemprov Padamkan Kebakaran TPA Bandarjaya, Tol Bakter Terganggu Asap Tebal Bandar Lampung Lampung Agendakan Beragam Rapat Penting, Revitalisasi Stadion Pahoman Jadi Sorotan Utama Lampung Selatan Kulkas Bekas Raib, Tiga Pria di Lampung Selatan Terancam Tujuh Tahun Penjara Hiburan Wendy Red Velvet Bersiap Comeback Solo November 2026, Janjikan Eksplorasi Vokal Hiburan Eiichiro Oda Ambil Jeda Dua Pekan, One Piece Chapter 1197 Tayang November 2026 Lampung Cuaca Lampung 20 Oktober 2026: Cerah Berawan Dominan, Waspada Hujan Lokal Lampung Tengah Kebakaran Landa TPA Bandarjaya Lampung Tengah, Gas Metan Diduga Pemicu Utama Pesawaran Pesawaran Jadi Pelopor Lampung, Lantik Pengurus Abpednas di 11 Kecamatan Lampung Tengah Asap Tebal TPA Bandar Jaya Picu Tabrakan Beruntun di Tol Trans-Sumatera, Dua Korban Luka Lampung Prakiraan Cuaca Lampung 19 Oktober 2026: Waspada Hujan Malam Hari Pemprov Lampung Kolaborasi Pemprov Padamkan Kebakaran TPA Bandarjaya, Tol Bakter Terganggu Asap Tebal Bandar Lampung Lampung Agendakan Beragam Rapat Penting, Revitalisasi Stadion Pahoman Jadi Sorotan Utama Lampung Selatan Kulkas Bekas Raib, Tiga Pria di Lampung Selatan Terancam Tujuh Tahun Penjara Hiburan Wendy Red Velvet Bersiap Comeback Solo November 2026, Janjikan Eksplorasi Vokal Hiburan Eiichiro Oda Ambil Jeda Dua Pekan, One Piece Chapter 1197 Tayang November 2026 Lampung Cuaca Lampung 20 Oktober 2026: Cerah Berawan Dominan, Waspada Hujan Lokal Lampung Tengah Kebakaran Landa TPA Bandarjaya Lampung Tengah, Gas Metan Diduga Pemicu Utama Pesawaran Pesawaran Jadi Pelopor Lampung, Lantik Pengurus Abpednas di 11 Kecamatan Lampung Tengah Asap Tebal TPA Bandar Jaya Picu Tabrakan Beruntun di Tol Trans-Sumatera, Dua Korban Luka Lampung Prakiraan Cuaca Lampung 19 Oktober 2026: Waspada Hujan Malam Hari

Modul:Tanggal waktu

Wikimedia module

Bagikan:
Dokumentasi modullihatsuntingriwayatsegarkan
Siap digunakanModul ini dinilai siap digunakan secara umum. Modul ini sudah matang dan diperkirakan bebas dari bug dan siap digunakan pada tempat yang tepat di manapun. Modul ini siap disinggung di halaman-halaman bantuan dan sumber informasi Wikipedia lainnya sebagai pilihan untuk dipelajari para pengguna baru. Untuk mengurangi beban server dan output yang tidak diharapkan, modul ini harus diperlengkapi dengan halaman bak pasir dan kasus uji daripada harus melakukan suntingan coba-dan-salah berulang-ulang.
WarningModul Lua ini digunakan pada banyak halaman dan perubahannya kemungkinan memicu perubahan massal pada semua halaman yang menggunakannya. Uji cobalah di subhalaman /bak pasir atau /kasus uji Modul:Tanggal waktu, atau bak pasir modul Anda. Pertimbangkan untuk mendiskusikan perubahan di halaman pembicaraan sebelum mengimplementasikannya.
Modul ini menggunakan Lua:

Modul:Date time menyediakan fungsi untuk memvalidasi dan memformat tanggal dalam templat seperti {{Start date}}, {{End date}}, {{Start date and age}}, dan {{End date and age}}.

Ini menangani:

  • Validasi komponen tanggal (tahun, bulan, hari)
  • Validasi komponen waktu (jam, menit, detik)
  • Pemformatan dan validasi zona waktu
  • Pembuatan markup mikroformat hCalendar yang sesuai
  • Perhitungan "time-ago"

Mengembalikan sebuah pesan galat dan kategori jika validasi gagal.

PenggunaanPenggunaan

Dokumentasi di atas ditransklusikan dari Modul:Tanggal waktu/doc. (sunting | riwayat)
Penyunting dapat melakukan uji coba pada halaman bak pasir (buat | cermin) dan kasus uji (buat) modul ini.
Subhalaman modul ini.
--[[
Module:Date time – Date formatting and validation module.
This module provides functions for validating and formatting dates in templates such as
{{Start date}}, {{End date}}, {{Start date and age}}, and {{End date and age}}. 
It handles:
- Validation of date components (year, month, day)
- Validation of time components (hour, minute, second)
- Timezone formatting and validation
- Generation of appropriate hCalendar microformat markup
- "time-ago" calculations
Design notes:
- Functions are organized into helper, validation, and formatting sections
- Error handling uses a consistent pattern with centralized error messages
- Timezone validation supports standard ISO 8601 formats
- Leap year calculation is cached for performance
]]
require("strict")
localp={}
---------------
-- Constants --
---------------
localHTML_SPACE=" "
localHTML_NBSP=" "
-- Error message constants
localERROR_MESSAGES={
integers="Semua nilai harus berupa integer",
has_leading_zeros="Nilai tidak boleh memiliki angka nol di depan yang tidak perlu",
missing_year="Nilai tahun diperlukan",
invalid_month="Nilai bukan berupa bulan yang valid",
missing_month="Nilai bulan diperlukan jika tanggal diberikan",
invalid_day="Nilai bukan hari yang valid (Bulan %d memiliki %d hari)",
invalid_hour="Nilai bukan berupa jam yang valid",
invalid_minute="Nilai bukan berupa menit yang valid",
invalid_second="Nilai bukan berupa detik yang valid",
timezone_incomplete_date="Zona waktu tidak dapat diatur tanpa hari dan jam",
invalid_timezone="Nilai bukan berupa zona waktu yang valid",
yes_value_parameter='%s harus antara "yes" atau "y"',
duplicate_parameters='Parameter duplikat digunakan: %s dan %s',
template="Templat tidak didukung",
time_without_hour="Menit dan detik membutuhkan nilai jam"
}
-- Template class mapping
-- "itvstart" and "itvend" are unique classes used by the TV infoboxes,
-- which only allow the usage of {{Start date}} and {{End date}}.
localTEMPLATE_CLASSES={
["start date"]="bday dtstart published updated itvstart",
["start date and age"]="bday dtstart published updated",
["end date"]="dtend itvend",
["end date and age"]="dtend"
}
-- Templates that require "time ago" calculations
localTIME_AGO={
["start date and age"]=true,
["end date and age"]=true
}
-- Indonesian month names
localMONTHS={
"Januari","Februari","Maret","April","Mei","Juni",
"Juli","Agustus","September","Oktober","November","Desember"
}
-- Error category
localERROR_CATEGORY="[[Kategori:Halaman yang menggunakan Modul:Tanggal waktu dengan nilai tidak valid]]"
-- Namespaces where error categories should be applied
localCATEGORY_NAMESPACES={
[0]=true,-- Article
[1]=true,-- Article talk
[4]=true,-- Wikipedia
[10]=true,-- Template
[100]=true,-- Portal
[118]=true-- Draft
}
-- Cached leap year calculations for performance
localleap_year_cache={}
-- Local variables for error handling
localhelp_link
----------------------
-- Helper Functions --
----------------------
--- Pads a number with leading zeros to ensure a minimum of two digits.
-- @param value (number|string) The value to pad with leading zeros
-- @return string The value padded to at least two digits, or nil if input is nil
localfunctionpad_left_zeros(value)
ifvalue==nilthen
returnnil
end
localstr=tostring(value)
returnstring.rep("0",math.max(0,2-#str))..str
end
--- Replaces [[U+2212]] (Unicode minus) with [[U+002D]] (ASCII hyphen) or vice versa.
-- @param value (string) The string value to process
-- @param to_unicode (boolean) If true, converts ASCII hyphen to Unicode minus;
--                            If false, converts Unicode minus to ASCII hyphen
-- @return string The processed string with appropriate minus characters, or nil if input is nil
localfunctionreplace_minus_character(value,to_unicode)
ifnotvaluethen
returnnil
end
ifto_unicodethen
returnvalue:gsub("-","−")
end
returnvalue:gsub("−","-")
end
--- Normalizes timezone format by ensuring proper padding of hours.
-- @param timezone (string) The timezone string to normalize
-- @return string The normalized timezone string with properly padded hours, or nil if input is nil
localfunctionfix_timezone(timezone)
ifnottimezonethen
returnnil
end
-- Replace U+2212 (Unicode minus) with U+002D (ASCII hyphen)
timezone=replace_minus_character(timezone,false)
-- Match the timezone pattern for ±H:MM format
localsign,hour,minutes=timezone:match("^([+-])(%d+):(%d+)$")
ifsignandhourandminutesthen
-- Pad the hour with a leading zero if necessary
hour=pad_left_zeros(hour)
returnsign..hour..":"..minutes
end
-- If no match, return the original timezone (this handles invalid or already padded timezones)
returntimezone
end
--- Checks if a timezone string is valid according to standard timezone formats.
-- Valid timezones range from UTC-12:00 to UTC+14:00.
-- @param timezone (string) The timezone string to validate
-- @return boolean true if the timezone is valid, false otherwise
localfunctionis_timezone_valid(timezone)
-- Consolidated timezone pattern for better performance
localvalid_patterns={
-- Z (UTC)
"^Z$",
-- Full timezone with minutes ±HH:MM
"^[+]0[1-9]:[0-5][0-9]$",
"^[+-]0[1-9]:[0-5][0-9]$",
"^[+-]1[0-2]:[0-5][0-9]$",
"^[+]1[34]:[0-5][0-9]$",
-- Whole hour timezones ±HH
"^[+-]0[1-9]$",
"^[+-]1[0-2]$",
"^[+]1[34]$",
-- Special cases
"^[+]00:00$",
"^[+]00$"
}
-- Additional checks for invalid -00 and -00:00 cases
iftimezone=="-00"ortimezone=="-00:00"then
returnfalse
end
for_,patterninipairs(valid_patterns)do
ifstring.match(timezone,pattern)then
returntrue
end
end
returnfalse
end
--- Checks if a given year is a leap year.
-- Uses a cache for better performance.
-- @param year (number) The year to check for leap year status
-- @return boolean true if the year is a leap year, false otherwise
localfunctionis_leap_year(year)
ifleap_year_cache[year]==nilthen
leap_year_cache[year]=(year%4==0andyear%100~=0)or(year%400==0)
end
returnleap_year_cache[year]
end
--- Returns the number of days in a given month of a specified year.
-- Handles leap years for February.
-- @param year (number) The year to check for leap year conditions
-- @param month (number) The month (1-12) for which to return the number of days
-- @return number The number of days in the specified month, accounting for leap years
localfunctionget_days_in_month(year,month)
localdays_in_month={31,28,31,30,31,30,31,31,30,31,30,31}
ifmonth==2andis_leap_year(year)then
return29
end
returndays_in_month[month]or0
end
--- Checks if a given value has invalid leading zeros.
-- @param value (string) The value to check for leading zeros
-- @param field_type (string) Field type ("day", "month", "hour", "minute", "second")
-- @return boolean true if the value has invalid leading zeros, false otherwise
localfunctionhas_leading_zeros(value,field_type)
value=tostring(value)
-- Common checks for day and month
iffield_type=="day"orfield_type=="month"then
-- Reject "00" and values with leading zero followed by more than one digit
returnvalue=="00"or
string.match(value,"^0[0-9][0-9]$")~=nilor
string.match(value,"^0[1-9][0-9]")~=nil
end
-- Checks for hour, minute, second
iffield_type=="hour"orfield_type=="minute"orfield_type=="second"then
-- Allow "00" and "01" to "09"
ifvalue=="00"orstring.match(value,"^0[1-9]$")then
returnfalse
end
-- Reject values starting with "0" followed by more than one digit
returnstring.match(value,"^0[0-9][0-9]+$")~=nil
end
returnfalse
end
--- Checks if a given value is an integer.
-- @param value (string|number) The value to check
-- @return boolean true if the value is a valid integer, false otherwise
localfunctionis_integer(value)
ifnotvaluethen
returnfalse
end
-- Check if the value is a number first
localnum_value=tonumber(value)
ifnotnum_valuethen
returnfalse
end
-- Check if it's an integer by comparing floor with the original
ifmath.floor(num_value)~=num_valuethen
returnfalse
end
-- For string inputs, check for decimal point to reject values like "7."
iftype(value)=="string"then
-- If the string contains a decimal point, it's not an integer
ifstring.find(value,"%.")then
returnfalse
end
end
returntrue
end
--- Returns the name of a month based on its numerical representation.
-- @param month_number (number) The month number (1-12)
-- @return string|nil The name of the month, or nil if invalid
localfunctionget_month_name(month_number)
month_number=tonumber(month_number)
returnMONTHS[month_number]
end
--- Generates an error message wrapped in HTML.
-- @param message (string) The error message to format
-- @param add_tracking_category (boolean, optional) If false, omits the tracking category
-- @return string An HTML-formatted error message with help link and error category
localfunctiongenerate_error(message,add_tracking_category)
localcategory=ERROR_CATEGORY
ifadd_tracking_category==falsethen
category=""
end
-- Get current page title object
localarticle_title=mw.title.getCurrentTitle()
-- Special case for testcases pages
localis_test_page=article_title.subpageText=="testcases"
localallow_this_test_page=article_title.fullText=="Module talk:Date time/testcases"
-- Remove category if the page is not in a tracked namespace or is any other testcases other than this module
if(notCATEGORY_NAMESPACES[article_title.namespace]andnotallow_this_test_page)
or(is_test_pageandnotallow_this_test_page)then
category=""
end
return'<strong class="error">Galat: '..message..'</strong> '..help_link..category
end
--------------------------
-- Formatting Functions --
--------------------------
--- Formats the time portion of a datetime string.
-- @param hour (string) The hour component
-- @param minute (string) The minute component
-- @param second (string) The second component
-- @return string The formatted time string, or empty string if hour is nil
localfunctionformat_time_string(hour,minute,second)
ifnothourthen
return""
end
localtime_string=string.format("%s:%s",hour,minute)
ifsecondandsecond~="00"andminute~="00"then
time_string=string.format("%s:%s",time_string,second)
end
returntime_string..","..HTML_SPACE
end
--- Formats the date portion of a datetime string based on the specified format.
-- @param year (string) The year component
-- @param month (string) The month component
-- @param day (string) The day component
-- @param date_format_dmy (string) The date format ("yes" or "y" for day-month-year, otherwise month-day-year)
-- @return string The formatted date string, or empty string if year is nil
localfunctionformat_date_string(year,month,day,date_format_dmy)
ifnotyearthen
return""
end
localdate_string
ifmonththen
localmonth_name=get_month_name(month)
ifdaythen
day=tonumber(day)
ifdate_format_dmythen
date_string=day..HTML_NBSP..month_name
else
date_string=month_name..HTML_NBSP..day..","
end
date_string=date_string..HTML_NBSP..year
else
date_string=month_name..HTML_NBSP..year
end
else
date_string=year
end
returndate_string
end
--- Formats the timezone portion of a datetime string.
-- @param timezone (string) The timezone component
-- @return string The formatted timezone string, or empty string if timezone is nil
localfunctionformat_timezone(timezone)
ifnottimezonethen
return""
end
returnHTML_SPACE..(timezone=="Z"and"(UTC)"or"("..timezone..")")
end
--- Generates an hCalendar microformat string for the given date-time values.
-- @param date_time_values (table) A table containing date and time components
-- @param classes (string) The CSS classes to apply to the microformat span
-- @return string The HTML for the hCalendar microformat
localfunctiongenerate_h_calendar(date_time_values,classes)
localparts={}
ifdate_time_values.yearthen
table.insert(parts,date_time_values.year)
ifdate_time_values.monththen
table.insert(parts,"-"..date_time_values.month)
ifdate_time_values.daythen
table.insert(parts,"-"..date_time_values.day)
end
end
ifdate_time_values.hourthen
table.insert(parts,"T"..date_time_values.hour)
ifdate_time_values.minutethen
table.insert(parts,":"..date_time_values.minute)
ifdate_time_values.secondthen
table.insert(parts,":"..date_time_values.second)
end
end
end
end
localh_calendar_content=table.concat(parts)..(date_time_values.timezoneor"")
localclass_span=string.format('<span class="%s">',classes)
returnstring.format(
'<span style="display: none;">%s(%s)</span>',
HTML_NBSP,
class_span..h_calendar_content..'</span>'
)
end
--- Generates a "time ago" string for age calculation templates.
-- @param date_time_values (table) Table containing date components (year, month, day)
-- @param br (boolean) Whether to include a line break before the time ago text
-- @param p (boolean) Whether to format with parentheses around the time ago text
-- @return string Formatted "time ago" text wrapped in a noprint span
localfunctionget_time_ago(date_time_values,br,p)
-- Build timestamp based on available date components
localtimestamp
localmin_magnitude
ifdate_time_values.daythen
-- Format with padding for month and day if needed
timestamp=string.format("%d-%02d-%02d",
date_time_values.year,
date_time_values.month,
date_time_values.day)
min_magnitude="days"
elseifdate_time_values.monththen
-- Format with padding for month if needed
timestamp=string.format("%d-%02d",
date_time_values.year,
date_time_values.month)
-- Get the current date
localcurrent_date=os.date("*t")
-- Compute the difference in months
localyear_diff=current_date.year-date_time_values.year
localmonth_diff=(year_diff*12)+(current_date.month-date_time_values.month)
-- If the difference is less than 12 months, use "months", otherwise "years"
ifmonth_diff<12then
min_magnitude="months"
else
min_magnitude="years"
end
else
timestamp=tostring(date_time_values.year)
min_magnitude="years"
end
-- Calculate time ago using [[Module:Time]] ago
localm_time_ago=require("Module:Time ago")._main
localtime_ago=m_time_ago({timestamp,["min_magnitude"]=min_magnitude})
-- Format the result based on br and p parameters
ifbrthen
time_ago=pand("<br/>("..time_ago..")")or(";<br/>"..time_ago)
else
time_ago=pand(HTML_SPACE.."("..time_ago..")")or(";"..HTML_SPACE..time_ago)
end
-- Wrap in noprint span
return"<span class=\"noprint\">"..time_ago.."</span>"
end
--------------------------
-- Validation Functions --
--------------------------
--- Validates the date and time values provided.
-- @param args (table) Table containing date and time values and optional parameters
-- @return nil|string Nil if validation passes, or an error message if validation fails
localfunction_validate_date_time(args)
localtemplate_name=args.templateor"start date"
help_link=string.format("<small>[[:Template:%s|(help)]]</small>",template_name)
-- Store and validate date-time values
localdate_time_values={
year=args[1],
month=args[2],
day=args[3],
hour=args[4],
minute=args[5],
second=args[6]
}
-- Validate each value
forkey,valueinpairs(date_time_values)do
ifvaluethen
-- Check for integer and leading zeros
ifnotis_integer(value)then
returngenerate_error(ERROR_MESSAGES.integers)
end
ifhas_leading_zeros(tostring(value),key)then
returngenerate_error(ERROR_MESSAGES.has_leading_zeros)
end
-- Convert to number
date_time_values[key]=tonumber(value)
end
end
-- Validate date components
ifnotdate_time_values.yearthen
returngenerate_error(ERROR_MESSAGES.missing_year)
end
ifdate_time_values.monthand(date_time_values.month<1ordate_time_values.month>12)then
returngenerate_error(ERROR_MESSAGES.invalid_month)
end
ifdate_time_values.daythen
ifnotdate_time_values.monththen
returngenerate_error(ERROR_MESSAGES.missing_month)
end
localmax_day=get_days_in_month(date_time_values.year,date_time_values.month)
ifdate_time_values.day<1ordate_time_values.day>max_daythen
returngenerate_error(string.format(ERROR_MESSAGES.invalid_day,date_time_values.month,max_day))
end
end
-- Validate time components
if(date_time_values.minuteordate_time_values.second)andnotdate_time_values.hourthen
returngenerate_error(ERROR_MESSAGES.time_without_hour)
end
ifdate_time_values.hourand(date_time_values.hour<0ordate_time_values.hour>23)then
returngenerate_error(ERROR_MESSAGES.invalid_hour)
end
ifdate_time_values.minuteand(date_time_values.minute<0ordate_time_values.minute>59)then
returngenerate_error(ERROR_MESSAGES.invalid_minute)
end
ifdate_time_values.secondand(date_time_values.second<0ordate_time_values.second>59)then
returngenerate_error(ERROR_MESSAGES.invalid_second)
end
-- Timezone cannot be set without a specific date and hour
ifargs[7]andnot(date_time_values.dayanddate_time_values.hour)then
returngenerate_error(ERROR_MESSAGES.timezone_incomplete_date)
elseifargs[7]andnotis_timezone_valid(args[7])then
returngenerate_error(ERROR_MESSAGES.invalid_timezone)
end
-- Validate that there aren't any duplicate parameters
ifargs.pandargs.parenthen
returngenerate_error(string.format(ERROR_MESSAGES.duplicate_parameters,"p","paren"))
end
-- Validate parameters that use "y" or "yes" for values	
localboolean_params={'df','p','paren','br'}
for_,param_nameinipairs(boolean_params)do
ifargs[param_name]andnot(args[param_name]=="yes"orargs[param_name]=="y")then
returngenerate_error(string.format(ERROR_MESSAGES.yes_value_parameter,param_name))
end
end
returnnil
end
----------------------
-- Public Functions --
----------------------
--- Validates date-time values from template arguments.
-- @param frame (table) The MediaWiki frame containing template arguments
-- @return nil|string Result of date-time validation
functionp.validate_date_time(frame)
localget_args=require("Module:Arguments").getArgs
localargs=get_args(frame)
-- Sanitize inputs
args[7]=fix_timezone(args[7])
return_validate_date_time(args)
end
--- Generates a formatted date string with microformat markup.
-- @param frame (table) The MediaWiki frame containing template arguments
-- @return string A formatted date string, or an error message if validation fails
functionp.generate_date(frame)
localget_args=require("Module:Arguments").getArgs
localargs=get_args(frame)
-- Sanitize inputs
args[7]=fix_timezone(args[7])
localvalidation_error=_validate_date_time(args)
ifvalidation_errorthen
returnvalidation_error
end
localclasses=TEMPLATE_CLASSES[args.templateor"start date"]
ifnotclassesthen
returngenerate_error(ERROR_MESSAGES.template,false)
end
-- Process date-time values
localdate_time_values={
year=args[1],
month=pad_left_zeros(args[2]),
day=pad_left_zeros(args[3]),
hour=pad_left_zeros(args[4]),
minute=args[5]andpad_left_zeros(args[5])or"00",
second=args[6]andpad_left_zeros(args[6])or"00",
timezone=replace_minus_character(args[7],true)-- Restore U+2212 (Unicode minus)
}
-- Generate individual components
localtime_string=format_time_string(
date_time_values.hour,
date_time_values.minute,
date_time_values.second
)
localdate_string=format_date_string(
date_time_values.year,
date_time_values.month,
date_time_values.day,
args.df
)
localtimezone_string=format_timezone(date_time_values.timezone)
localtime_ago=""
ifTIME_AGO[args.template]then
time_ago=get_time_ago(
date_time_values,
args.br,
args.porargs.paren
)
end
localh_calendar=generate_h_calendar(date_time_values,classes)
-- Combine components
returntime_string..date_string..timezone_string..time_ago..h_calendar
end
returnp
Konten disalin dari Wikipedia Bahasa Indonesia (lisensi CC BY-SA) Lihat versi asli di Wikipedia

Rekomendasi Pilihan