diff --git a/Cargo.lock b/Cargo.lock
index 8708636..8e2487f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -405,6 +405,12 @@ version = "2.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
 
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
 [[package]]
 name = "nix"
 version = "0.29.0"
@@ -417,6 +423,16 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
 [[package]]
 name = "ntapi"
 version = "0.4.1"
@@ -482,6 +498,17 @@ dependencies = [
  "unicode-width 0.2.0",
 ]
 
+[[package]]
+name = "parse_datetime"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8720474e3dd4af20cea8716703498b9f3b690f318fa9d9d9e2e38eaf44b96d0"
+dependencies = [
+ "chrono",
+ "nom",
+ "regex",
+]
+
 [[package]]
 name = "phf"
 version = "0.11.2"
@@ -1012,6 +1039,7 @@ version = "0.0.1"
 dependencies = [
  "chrono",
  "clap",
+ "parse_datetime",
  "regex",
  "serde",
  "serde_json",
diff --git a/src/uu/dmesg/Cargo.toml b/src/uu/dmesg/Cargo.toml
index c6a8870..e154767 100644
--- a/src/uu/dmesg/Cargo.toml
+++ b/src/uu/dmesg/Cargo.toml
@@ -17,6 +17,7 @@ regex = { workspace = true }
 serde_json = { workspace = true }
 serde = { workspace = true }
 chrono = "0.4.38"
+parse_datetime = "0.6.0"
 
 [features]
 fixed-boot-time = []
diff --git a/src/uu/dmesg/src/dmesg.rs b/src/uu/dmesg/src/dmesg.rs
index 75bfe8f..96c995b 100644
--- a/src/uu/dmesg/src/dmesg.rs
+++ b/src/uu/dmesg/src/dmesg.rs
@@ -3,11 +3,18 @@
 // For the full copyright and license information, please view the LICENSE
 // file that was distributed with this source code.
 
+use chrono::{DateTime, FixedOffset};
 use clap::{crate_version, Arg, ArgAction, Command};
 use regex::Regex;
-use std::fs;
+use std::{
+    collections::HashSet,
+    fs::File,
+    hash::Hash,
+    io::{BufRead, BufReader},
+    sync::OnceLock,
+};
 use uucore::{
-    error::{FromIo, UResult, USimpleError},
+    error::{FromIo, UError, UResult, USimpleError},
     format_usage, help_about, help_usage,
 };
 
@@ -43,7 +50,69 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
             }
         };
     }
-    dmesg.parse()?.print();
+    if let Some(list_args) = matches.get_many::<String>(options::FACILITY) {
+        let mut facility_filters = HashSet::new();
+        for list in list_args {
+            for arg in list.split(',') {
+                let facility = match arg {
+                    "kern" => Facility::Kern,
+                    "user" => Facility::User,
+                    "mail" => Facility::Mail,
+                    "daemon" => Facility::Daemon,
+                    "auth" => Facility::Auth,
+                    "syslog" => Facility::Syslog,
+                    "lpr" => Facility::Lpr,
+                    "news" => Facility::News,
+                    "uucp" => Facility::Uucp,
+                    "cron" => Facility::Cron,
+                    "authpriv" => Facility::Authpriv,
+                    "ftp" => Facility::Ftp,
+                    "res0" => Facility::Res0,
+                    "res1" => Facility::Res1,
+                    "res2" => Facility::Res2,
+                    "res3" => Facility::Res3,
+                    "local0" => Facility::Local0,
+                    "local1" => Facility::Local1,
+                    "local2" => Facility::Local2,
+                    "local3" => Facility::Local3,
+                    "local4" => Facility::Local4,
+                    "local5" => Facility::Local5,
+                    "local6" => Facility::Local6,
+                    "local7" => Facility::Local7,
+                    _ => return Err(USimpleError::new(1, format!("unknown facility '{arg}'"))),
+                };
+                facility_filters.insert(facility);
+            }
+        }
+        dmesg.facility_filters = Some(facility_filters);
+    }
+    if let Some(list_args) = matches.get_many::<String>(options::LEVEL) {
+        let mut level_filters = HashSet::new();
+        for list in list_args {
+            for arg in list.split(',') {
+                let level = match arg {
+                    "emerg" => Level::Emerg,
+                    "alert" => Level::Alert,
+                    "crit" => Level::Crit,
+                    "err" => Level::Err,
+                    "warn" => Level::Warn,
+                    "notice" => Level::Notice,
+                    "info" => Level::Info,
+                    "debug" => Level::Debug,
+                    _ => return Err(USimpleError::new(1, format!("unknown level '{arg}'"))),
+                };
+                level_filters.insert(level);
+            }
+        }
+        dmesg.level_filters = Some(level_filters);
+    }
+    if let Some(since) = matches.get_one::<String>(options::SINCE) {
+        dmesg.since_filter = Some(time_formatter::parse_datetime(since)?);
+    }
+    if let Some(until) = matches.get_one::<String>(options::UNTIL) {
+        dmesg.until_filter = Some(time_formatter::parse_datetime(until)?);
+    }
+    dmesg.print()?;
     Ok(())
 }
 
@@ -75,19 +144,52 @@ pub fn uu_app() -> Command {
                 )
                 .action(ArgAction::Set),
         )
+        .arg(
+            Arg::new(options::FACILITY)
+                .short('f')
+                .long("facility")
+                .help("restrict output to defined facilities")
+                .action(ArgAction::Append),
+        )
+        .arg(
+            Arg::new(options::LEVEL)
+                .short('l')
+                .long("level")
+                .help("restrict output to defined levels")
+                .action(ArgAction::Append),
+        )
+        .arg(
+            Arg::new(options::SINCE)
+                .long("since")
+                .help("display the lines since the specified time")
+                .action(ArgAction::Set),
+        )
+        .arg(
+            Arg::new(options::UNTIL)
+                .long("until")
+                .help("display the lines until the specified time")
+                .action(ArgAction::Set),
+        )
 }
 
 mod options {
     pub const KMSG_FILE: &str = "kmsg-file";
     pub const JSON: &str = "json";
     pub const TIME_FORMAT: &str = "time-format";
+    pub const FACILITY: &str = "facility";
+    pub const LEVEL: &str = "level";
+    pub const SINCE: &str = "since";
+    pub const UNTIL: &str = "until";
 }
 
 struct Dmesg<'a> {
     kmsg_file: &'a str,
     output_format: OutputFormat,
     time_format: TimeFormat,
-    records: Option<Vec<Record>>,
+    facility_filters: Option<HashSet<Facility>>,
+    level_filters: Option<HashSet<Level>>,
+    since_filter: Option<chrono::DateTime<chrono::FixedOffset>>,
+    until_filter: Option<chrono::DateTime<chrono::FixedOffset>>,
 }
 
 impl Dmesg<'_> {
@@ -96,86 +198,105 @@ impl Dmesg<'_> {
             kmsg_file: "/dev/kmsg",
             output_format: OutputFormat::Normal,
             time_format: TimeFormat::Raw,
-            records: None,
+            facility_filters: None,
+            level_filters: None,
+            since_filter: None,
+            until_filter: None,
         }
     }
 
-    fn parse(mut self) -> UResult<Self> {
-        let mut records = vec![];
-        let re = Self::record_regex();
-        let lines = self.read_lines_from_kmsg_file()?;
-        for line in lines {
-            for (_, [pri_fac, seq, time, msg]) in re.captures_iter(&line).map(|c| c.extract()) {
-                records.push(Record::from_str_fields(
-                    pri_fac,
-                    seq,
-                    time,
-                    msg.to_string(),
-                )?);
-            }
-        }
-        self.records = Some(records);
-        Ok(self)
-    }
-
-    fn record_regex() -> Regex {
-        let valid_number_pattern = "0|[1-9][0-9]*";
-        let additional_fields_pattern = ",^[,;]*";
-        let record_pattern = format!(
-            "(?m)^({0}),({0}),({0}),.(?:{1})*;(.*)$",
-            valid_number_pattern, additional_fields_pattern
-        );
-        Regex::new(&record_pattern).expect("invalid regex.")
-    }
-
-    fn read_lines_from_kmsg_file(&self) -> UResult<Vec<String>> {
-        let kmsg_bytes = fs::read(self.kmsg_file)
-            .map_err_context(|| format!("cannot open {}", self.kmsg_file))?;
-        let lines = kmsg_bytes
-            .split(|&byte| byte == 0)
-            .map(|line| String::from_utf8_lossy(line).to_string())
-            .collect();
-        Ok(lines)
-    }
-
-    fn print(&self) {
+    fn print(&self) -> UResult<()> {
         match self.output_format {
             OutputFormat::Json => self.print_json(),
             OutputFormat::Normal => self.print_normal(),
         }
     }
 
-    fn print_json(&self) {
-        if let Some(records) = &self.records {
-            println!("{}", json::serialize_records(records));
+    fn print_json(&self) -> UResult<()> {
+        let records: UResult<Vec<Record>> = self.try_filtered_iter()?.collect();
+        println!("{}", json::serialize_records(&records?));
+        Ok(())
+    }
+
+    fn print_normal(&self) -> UResult<()> {
+        let mut reltime_formatter = time_formatter::ReltimeFormatter::new();
+        let mut delta_formatter = time_formatter::DeltaFormatter::new();
+        for record in self.try_filtered_iter()? {
+            let record = record?;
+            match self.time_format {
+                TimeFormat::Delta => {
+                    print!("[{}] ", delta_formatter.format(record.timestamp_us))
+                }
+                TimeFormat::Reltime => {
+                    print!("[{}] ", reltime_formatter.format(record.timestamp_us))
+                }
+                TimeFormat::Ctime => {
+                    print!("[{}] ", time_formatter::ctime(record.timestamp_us))
+                }
+                TimeFormat::Iso => {
+                    print!("{} ", time_formatter::iso(record.timestamp_us))
+                }
+                TimeFormat::Raw => {
+                    print!("[{}] ", time_formatter::raw(record.timestamp_us))
+                }
+                TimeFormat::Notime => (),
+            }
+            println!("{}", record.message);
+        }
+        Ok(())
+    }
+
+    fn try_filtered_iter(&self) -> UResult<impl Iterator<Item = UResult<Record>> + '_> {
+        Ok(self
+            .try_iter()?
+            .filter(Self::is_record_in_set(&self.facility_filters))
+            .filter(Self::is_record_in_set(&self.level_filters))
+            .filter(Self::is_record_since(&self.since_filter))
+            .filter(Self::is_record_until(&self.until_filter)))
+    }
+
+    fn try_iter(&self) -> UResult<RecordIterator> {
+        let file = File::open(self.kmsg_file)
+            .map_err_context(|| format!("cannot open {}", self.kmsg_file))?;
+        let file_reader = BufReader::new(file);
+        Ok(RecordIterator { file_reader })
+    }
+
+    fn is_record_in_set<T>(
+        set: &Option<HashSet<T>>,
+    ) -> impl Fn(&Result<Record, Box<dyn UError>>) -> bool + '_
+    where
+        T: From<u32> + Eq + Hash,
+    {
+        move |record: &UResult<Record>| match (record, set) {
+            (Ok(record), Some(set)) => set.contains(&T::from(record.priority_facility)),
+            _ => true,
         }
     }
 
-    fn print_normal(&self) {
-        if let Some(records) = &self.records {
-            let mut reltime_formatter = time_formatter::ReltimeFormatter::new();
-            let mut delta_formatter = time_formatter::DeltaFormatter::new();
-            for record in records {
-                match self.time_format {
-                    TimeFormat::Delta => {
-                        print!("[{}] ", delta_formatter.format(record.timestamp_us))
-                    }
-                    TimeFormat::Reltime => {
-                        print!("[{}] ", reltime_formatter.format(record.timestamp_us))
-                    }
-                    TimeFormat::Ctime => {
-                        print!("[{}] ", time_formatter::ctime(record.timestamp_us))
-                    }
-                    TimeFormat::Iso => {
-                        print!("{} ", time_formatter::iso(record.timestamp_us))
-                    }
-                    TimeFormat::Raw => {
-                        print!("[{}] ", time_formatter::raw(record.timestamp_us))
-                    }
-                    TimeFormat::Notime => (),
-                }
-                println!("{}", record.message);
+    fn is_record_since(
+        since: &Option<DateTime<FixedOffset>>,
+    ) -> impl Fn(&UResult<Record>) -> bool + '_ {
+        move |record: &UResult<Record>| match (record, since) {
+            (Ok(record), Some(since)) => {
+                let time =
+                    time_formatter::datetime_from_microseconds_since_boot(record.timestamp_us);
+                time >= *since
             }
+            _ => true,
+        }
+    }
+
+    fn is_record_until(
+        until: &Option<DateTime<FixedOffset>>,
+    ) -> impl Fn(&UResult<Record>) -> bool + '_ {
+        move |record: &UResult<Record>| match (record, until) {
+            (Ok(record), Some(until)) => {
+                let time =
+                    time_formatter::datetime_from_microseconds_since_boot(record.timestamp_us);
+                time <= *until
+            }
+            _ => true,
         }
     }
 }
@@ -194,6 +315,102 @@ enum TimeFormat {
     Raw,
 }
 
+#[derive(Eq, Hash, PartialEq)]
+enum Facility {
+    Kern,
+    User,
+    Mail,
+    Daemon,
+    Auth,
+    Syslog,
+    Lpr,
+    News,
+    Uucp,
+    Cron,
+    Authpriv,
+    Ftp,
+    Res0,
+    Res1,
+    Res2,
+    Res3,
+    Local0,
+    Local1,
+    Local2,
+    Local3,
+    Local4,
+    Local5,
+    Local6,
+    Local7,
+    Unknown,
+}
+
+#[derive(Eq, Hash, PartialEq)]
+enum Level {
+    Emerg,
+    Alert,
+    Crit,
+    Err,
+    Warn,
+    Notice,
+    Info,
+    Debug,
+    Unknown,
+}
+
+struct RecordIterator {
+    file_reader: BufReader<File>,
+}
+
+impl Iterator for RecordIterator {
+    type Item = UResult<Record>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match self.read_record_line() {
+            Err(e) => Some(Err(e)),
+            Ok(None) => None,
+            Ok(Some(line)) => match self.parse_record(&line) {
+                None => self.next(),
+                Some(record) => Some(Ok(record)),
+            },
+        }
+    }
+}
+
+impl RecordIterator {
+    fn read_record_line(&mut self) -> UResult<Option<String>> {
+        let mut buf = vec![];
+        let num_bytes = self.file_reader.read_until(0, &mut buf)?;
+        match num_bytes {
+            0 => Ok(None),
+            _ => Ok(Some(String::from_utf8_lossy(&buf).to_string())),
+        }
+    }
+
+    fn parse_record(&self, record_line: &str) -> Option<Record> {
+        record_regex()
+            .captures_iter(record_line)
+            .map(|c| c.extract())
+            .filter_map(|(_, [pri_fac, seq, time, msg])| {
+                Record::from_str_fields(pri_fac, seq, time, msg.to_string()).ok()
+            })
+            .next()
+    }
+}
+
+fn record_regex() -> &'static Regex {
+    RECORD_REGEX.get_or_init(|| {
+        let valid_number_pattern = "0|[1-9][0-9]*";
+        let additional_fields_pattern = ",^[,;]*";
+        let record_pattern = format!(
+            "(?m)^({0}),({0}),({0}),.(?:{1})*;(.*)$",
+            valid_number_pattern, additional_fields_pattern
+        );
+        Regex::new(&record_pattern).expect("invalid regex.")
+    })
+}
+
+static RECORD_REGEX: OnceLock<Regex> = OnceLock::new();
+
 struct Record {
     priority_facility: u32,
     _sequence: u64,
@@ -217,3 +434,53 @@ impl Record {
         }
     }
 }
+
+impl From<u32> for Level {
+    fn from(value: u32) -> Self {
+        let priority = value & 0b111;
+        match priority {
+            0 => Level::Emerg,
+            1 => Level::Alert,
+            2 => Level::Crit,
+            3 => Level::Err,
+            4 => Level::Warn,
+            5 => Level::Notice,
+            6 => Level::Info,
+            7 => Level::Debug,
+            _ => Level::Unknown,
+        }
+    }
+}
+
+impl From<u32> for Facility {
+    fn from(value: u32) -> Self {
+        let facility = (value >> 3) as u8;
+        match facility {
+            0 => Facility::Kern,
+            1 => Facility::User,
+            2 => Facility::Mail,
+            3 => Facility::Daemon,
+            4 => Facility::Auth,
+            5 => Facility::Syslog,
+            6 => Facility::Lpr,
+            7 => Facility::News,
+            8 => Facility::Uucp,
+            9 => Facility::Cron,
+            10 => Facility::Authpriv,
+            11 => Facility::Ftp,
+            12 => Facility::Res0,
+            13 => Facility::Res1,
+            14 => Facility::Res2,
+            15 => Facility::Res3,
+            16 => Facility::Local0,
+            17 => Facility::Local1,
+            18 => Facility::Local2,
+            19 => Facility::Local3,
+            20 => Facility::Local4,
+            21 => Facility::Local5,
+            22 => Facility::Local6,
+            23 => Facility::Local7,
+            _ => Facility::Unknown,
+        }
+    }
+}
diff --git a/src/uu/dmesg/src/time_formatter.rs b/src/uu/dmesg/src/time_formatter.rs
index 198431f..f26bb4c 100644
--- a/src/uu/dmesg/src/time_formatter.rs
+++ b/src/uu/dmesg/src/time_formatter.rs
@@ -7,6 +7,7 @@ use chrono::{DateTime, FixedOffset, TimeDelta};
 #[cfg(feature = "fixed-boot-time")]
 use chrono::{NaiveDate, NaiveTime};
 use std::sync::OnceLock;
+use uucore::error::{UResult, USimpleError};
 
 pub fn raw(timestamp_us: i64) -> String {
     let seconds = timestamp_us / 1000000;
@@ -116,6 +117,17 @@ impl DeltaFormatter {
     }
 }
 
+pub fn parse_datetime(s: &str) -> UResult<DateTime<FixedOffset>> {
+    parse_datetime::parse_datetime(s)
+        .map_err(|_| USimpleError::new(1, format!("invalid time value \"{s}\"")))
+}
+
+pub fn datetime_from_microseconds_since_boot(microseconds: i64) -> DateTime<FixedOffset> {
+    boot_time()
+        .checked_add_signed(TimeDelta::microseconds(microseconds))
+        .unwrap()
+}
+
 static BOOT_TIME: OnceLock<DateTime<FixedOffset>> = OnceLock::new();
 
 #[cfg(feature = "fixed-boot-time")]
diff --git a/tests/by-util/test_dmesg.rs b/tests/by-util/test_dmesg.rs
index b811584..2debb8a 100644
--- a/tests/by-util/test_dmesg.rs
+++ b/tests/by-util/test_dmesg.rs
@@ -81,3 +81,111 @@ fn test_invalid_time_format() {
         .code_is(1)
         .stderr_only("dmesg: unknown time format: definitely-invalid\n");
 }
+
+#[test]
+fn test_filter_facility() {
+    let facilities = [
+        "kern", "user", "mail", "daemon", "auth", "syslog", "lpr", "news", "uucp", "cron",
+        "authpriv", "ftp", "local0", "local1", "local2", "local3", "local4", "local5", "local6",
+        "local7",
+    ];
+    for facility in facilities {
+        let facility_filter_arg = format!("--facility={facility}");
+        let mut cmd = new_ucmd!();
+        let result = cmd
+            .arg("--kmsg-file")
+            .arg("kmsg.input")
+            .arg(facility_filter_arg)
+            .succeeds();
+        let stdout = result.no_stderr().stdout_str();
+        assert_eq!(stdout.lines().count(), 8);
+        let expected = format!("LOG_{}", facility.to_uppercase());
+        stdout
+            .lines()
+            .for_each(|line| assert!(line.contains(&expected)));
+    }
+}
+
+#[test]
+fn test_filter_levels() {
+    let levels = [
+        "emerg", "alert", "crit", "err", "warn", "notice", "info", "debug",
+    ];
+    for level in levels {
+        let level_filter_arg = format!("--level={level}");
+        let mut cmd = new_ucmd!();
+        let result = cmd
+            .arg("--kmsg-file")
+            .arg("kmsg.input")
+            .arg(level_filter_arg)
+            .succeeds();
+        let stdout = result.no_stderr().stdout_str();
+        assert_eq!(stdout.lines().count(), 20);
+        let expected = format!("LOG_{}", level.to_uppercase());
+        stdout
+            .lines()
+            .for_each(|line| assert!(line.contains(&expected)));
+    }
+}
+
+#[test]
+fn test_invalid_facility_argument() {
+    new_ucmd!()
+        .arg("--facility=definitely-invalid")
+        .fails()
+        .code_is(1)
+        .stderr_only("dmesg: unknown facility 'definitely-invalid'\n");
+}
+
+#[test]
+fn test_invalid_level_argument() {
+    new_ucmd!()
+        .arg("--level=definitely-invalid")
+        .fails()
+        .code_is(1)
+        .stderr_only("dmesg: unknown level 'definitely-invalid'\n");
+}
+
+#[test]
+fn test_filter_multiple() {
+    let mut cmd = new_ucmd!();
+    let result = cmd
+        .arg("--kmsg-file")
+        .arg("kmsg.input")
+        .arg("--facility=kern,user")
+        .arg("--level=emerg,alert")
+        .succeeds();
+    let stdout = result.no_stderr().stdout_str();
+    assert_eq!(stdout.lines().count(), 4);
+    stdout.lines().for_each(|line| {
+        assert!(
+            (line.contains("LOG_KERN") || line.contains("LOG_USER"))
+                && (line.contains("LOG_EMERG") || line.contains("LOG_ALERT"))
+        )
+    });
+}
+
+#[test]
+fn test_since_until() {
+    new_ucmd!()
+        .arg("--kmsg-file")
+        .arg("kmsg.input")
+        .arg("--since=2024-11-19 17:47:32 +0700")
+        .arg("--until=2024-11-19 18:55:52 +0700")
+        .succeeds()
+        .no_stderr()
+        .stdout_is_templated_fixture("test_since_until.expected", &[("\r\n", "\n")]);
+}
+
+#[test]
+fn test_since_until_invalid_time() {
+    let options = ["--since", "--until"];
+    for option in options {
+        new_ucmd!()
+            .arg(format!("{option}=definitely-invalid"))
+            .fails()
+            .stderr_only(format!(
+                "dmesg: invalid time value \"definitely-invalid\"\n"
+            ));
+    }
+}
diff --git a/tests/fixtures/dmesg/test_since_until.expected b/tests/fixtures/dmesg/test_since_until.expected
new file mode 100644
index 0000000..2b76c31
--- /dev/null
+++ b/tests/fixtures/dmesg/test_since_until.expected
@@ -0,0 +1,5 @@
+[80000.000000] LOG_WARNING LOG_AUTH
+[81000.000000] LOG_WARNING LOG_AUTHPRIV
+[82000.000000] LOG_WARNING LOG_CRON
+[83000.000000] LOG_WARNING LOG_DAEMON
+[84000.000000] LOG_WARNING LOG_FTP