Skip to content

Conversation

@Shamzik
Copy link
Contributor

@Shamzik Shamzik commented Dec 8, 2025

This first part of implementing Date/Time classes. Here implemented:

  • DateInterval;
  • DateTimeZone;
  • DateTimeImmutable;
  • DateTime.

@Shamzik Shamzik marked this pull request as ready for review December 10, 2025 10:26
@Shamzik Shamzik self-assigned this Dec 10, 2025
@Shamzik Shamzik added the k2 k2 related label Dec 10, 2025
@Shamzik Shamzik added this to the next milestone Dec 10, 2025
@Shamzik Shamzik changed the title [k2] add Date/Time classes (except DateTime) to light runtime [k2] add Date/Time classes to light runtime Dec 10, 2025
class string {
public:
using size_type = string_size_type;
using value_type = char;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was added to be able to use std::back_inserter

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not change core KPHP types

@Shamzik Shamzik requested a review from apolyakov December 12, 2025 11:44
@DrDet DrDet modified the milestones: 14.12.2025, next Dec 12, 2025
Copy link
Contributor

@apolyakov apolyakov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've reviewed and noted some comments. Please, take into account that these comments should be applied to whole PR, not only the places where I left those comments

inline constexpr std::string_view BACKSLASH_ = "\\";
inline constexpr std::string_view QUOTE_ = "\"";
inline constexpr std::string_view NEWLINE_ = "\n";
inline constexpr std::string_view NOW_ = "now";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the context for strings part of standard library. Let's move this to one specific for time functions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


#include "kphp/timelib/timelib.h"

#include "common/containers/final_action.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, remove all the unused includes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


using error_container_t = std::unique_ptr<timelib_error_container, destructor>;
using rel_time_t = std::unique_ptr<timelib_rel_time, destructor>;
using time_t = std::unique_ptr<timelib_time, destructor>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we have a mix of raw timelib types and our own wrappers in the API. It doesn't look like a good solution.

Also, please refactor exisiting code that uses raw types in case you add wrappers. Mixing types is always bad

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed except clone function


time_offset_t construct_time_offset(timelib_time& t) noexcept;

std::pair<time_t, error_container_t> parse_time(std::string_view time_sv) noexcept;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for us to have both valid time_t and error_container_t?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error_container_t is always non-null here. time_t is null in case of an error.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, it seems that std::expected<std::pair<time, error>, error> is the right choice here


time_t add(timelib_time& t, timelib_rel_time& interval) noexcept;

rel_time_t clone(timelib_rel_time& rt) noexcept;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it better to just create a wrapper class? As far as I see, it might be worth it since you already have clone and destruct

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've refactored the header to make it easier to read. This library isn't very friendly to creating wrapper classes around it.

@Shamzik Shamzik requested a review from apolyakov January 16, 2026 16:14

} // namespace timezones

inline constexpr std::string_view NOW_ = "now";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't look like it should be public

constexpr inline std::array<std::string_view, 7> DAY_FULL_NAMES = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
constexpr inline std::array<std::string_view, 7> DAY_SHORT_NAMES = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

struct error_container_destructor {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it supposed to be manually used by a user of kphp::timelib?

}
};

using error_container_t = std::unique_ptr<timelib_error_container, kphp::timelib::error_container_destructor>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest to get rid of _t suffix

using time_t = std::unique_ptr<timelib_time, kphp::timelib::time_destructor>;

/* === rel_time === */
std::expected<kphp::timelib::rel_time_t, kphp::timelib::error_container_t> parse_interval(std::string_view format) noexcept;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what does this function do. Its name is parse_interval while it accepts some format? What does format mean here?


/* === rel_time === */
std::expected<kphp::timelib::rel_time_t, kphp::timelib::error_container_t> parse_interval(std::string_view format) noexcept;
kphp::timelib::rel_time_t clone_time_interval(const kphp::timelib::time_t& t) noexcept;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is kphp::timelib::time_t an interval? It seems more like a timepoint

class string {
public:
using size_type = string_size_type;
using value_type = char;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not change core KPHP types

timelib_sll isoweek{};
timelib_sll isoyear{};

for (std::size_t i{0}; i < format.size(); ++i) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't use std:: for primitive types


template<typename OutputIt>
OutputIt format_to(OutputIt out, std::string_view format, const kphp::timelib::time_t& t) noexcept {
return kphp::timelib::details::format_to<OutputIt>(out, format, t, t->is_localtime);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the approach to implement format_to for time and rel_time differs?

options |= TIMELIB_OVERRIDE_TIME;
}

kphp::memory::libc_alloc_guard{}, timelib_fill_holes(time.get(), now_time.get(), options);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

libc_alloc_guard{} is not free in terms of performance. Try to use it as less as possible

case 'o':
if (!weekYearSet) {
timelib_isoweek_from_date(t->y, t->m, t->d, std::addressof(isoweek), std::addressof(isoyear));
weekYearSet = 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implicit cast here

}

void update_last_errors(kphp::timelib::error_container_t&& new_errors) noexcept {
last_errors.swap(new_errors);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is seems unnecessary to waste CPU cycles to move a value back to new_errors

@@ -0,0 +1,34 @@
// Compiler for PHP (aka KPHP)
// Copyright (c) 2022 LLC «V Kontakte»
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, do not let copy paste introduce errors. Change the year to 2025

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's follow our style and name files like datetime-zone.h

return self;
}

string f$DateTimeZone$$getName(const class_instance<C$DateTimeZone>& self) noexcept {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the reason to move these definitions into the cpp file?

kphp::log::warning("DateInterval::createFromDateString(): Unknown or bad format ({}) {}", datetime.c_str(), errors);
return {};
}
class_instance<C$DateInterval> date_interval;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is make_instance alternative

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

k2 k2 related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants