plugin types FEATURE add time-period plugin

Implemented plugin for the libnetconf2-netconf-server YANG module's
time-period type.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a838daa..b15c1f4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -106,7 +106,8 @@
     src/plugins_types/date_and_time.c
     src/plugins_types/hex_string.c
     src/plugins_types/xpath1.0.c
-    src/plugins_types/node_instanceid.c)
+    src/plugins_types/node_instanceid.c
+    src/plugins_types/time_period.c)
 
 set(libsrc
     src/ly_common.c
diff --git a/src/plugins.c b/src/plugins.c
index 5ff6616..22c4947 100644
--- a/src/plugins.c
+++ b/src/plugins.c
@@ -81,6 +81,11 @@
 extern const struct lyplg_type_record plugins_node_instanceid[];
 
 /*
+ * libnetconf2-netconf-server
+ */
+extern const struct lyplg_type_record plugins_time_period[];
+
+/*
  * lyds_tree
  */
 extern const struct lyplg_type_record plugins_lyds_tree[];
@@ -522,6 +527,9 @@
         LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_hex_string), error);
         LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_xpath10), error);
 
+        /* libnetconf2-netconf-server */
+        LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_time_period), error);
+
         /* ietf-netconf-acm */
         LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_node_instanceid), error);
 
diff --git a/src/plugins_types/time_period.c b/src/plugins_types/time_period.c
new file mode 100644
index 0000000..e2fbcd6
--- /dev/null
+++ b/src/plugins_types/time_period.c
@@ -0,0 +1,100 @@
+/**
+ * @file time_period.c
+ * @author Roman Janota <janota@cesnet.cz>
+ * @brief libnetconf2-netconf-server time-period type plugin.
+ *
+ * Copyright (c) 2024 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://opensource.org/licenses/BSD-3-Clause
+ */
+
+#include "plugins_types.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "libyang.h"
+
+#include "compat.h"
+#include "ly_common.h"
+#include "plugins_internal.h" /* LY_TYPE_*_STR */
+
+/**
+ * @page howtoDataLYB LYB Binary Format
+ * @subsection howtoDataLYBTypesTimePeriod time-period (libnetconf2-netconf-server)
+ *
+ * | Size (B) | Mandatory | Type | Meaning |
+ * | :------  | :-------: | :--: | :-----: |
+ * | string length | yes | `char *` | time in either months, weeks, days, or hours |
+ */
+
+/**
+ * @brief Implementation of ::lyplg_type_sort_clb for libnetconf2-netconf-server time-period type.
+ *
+ * The values are sorted in descending order, i.e. the longest expiration time comes first.
+ */
+static int
+lyplg_type_sort_time_period(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
+{
+    const char *value1, *value2;
+    char unit1, unit2;
+    long v1, v2;
+
+    value1 = lyd_value_get_canonical(ctx, val1);
+    value2 = lyd_value_get_canonical(ctx, val2);
+
+    /* get the units (last character) and the values (all characters except the last one) */
+    unit1 = value1[strlen(value1) - 1];
+    unit2 = value2[strlen(value2) - 1];
+    v1 = strtol(value1, NULL, 10);
+    v2 = strtol(value2, NULL, 10);
+
+    /* descending order */
+    if (unit1 == unit2) {
+        if (v1 > v2) {
+            return -1;
+        } else if (v1 == v2) {
+            return 0;
+        } else {
+            return 1;
+        }
+    } else if (unit1 == 'm') {
+        return -1;
+    } else if ((unit1 == 'w') && (unit2 != 'm')) {
+        return -1;
+    } else if ((unit1 == 'd') && (unit2 == 'h')) {
+        return -1;
+    } else {
+        return 1;
+    }
+}
+
+/**
+ * @brief Plugin information for time-period type implementation.
+ *
+ * Note that external plugins are supposed to use:
+ *
+ *   LYPLG_TYPES = {
+ */
+const struct lyplg_type_record plugins_time_period[] = {
+    {
+        .module = "libnetconf2-netconf-server",
+        .revision = "2024-07-09",
+        .name = "time-period",
+
+        .plugin.id = "libyang 2 - time-period, version 1",
+        .plugin.store = lyplg_type_store_string,
+        .plugin.validate = NULL,
+        .plugin.compare = lyplg_type_compare_simple,
+        .plugin.sort = lyplg_type_sort_time_period,
+        .plugin.print = lyplg_type_print_simple,
+        .plugin.duplicate = lyplg_type_dup_simple,
+        .plugin.free = lyplg_type_free_simple,
+        .plugin.lyb_data_len = -1,
+    },
+    {0}
+};