There is no universal solution to Y2038. Each development environment and programming language has unique issues and potential solutions. Depending on various constraints, some options are available, each with its own advantages and disadvantages.
Moving to Y2038-compliant 64-bit hardware platform, OS, and tools is the simplest part of the solution (if that is possible for your projects). This should provides 64-bit time functions. Existing code still needs to be checked for Y2038 issues. Y2038-compliant versions of any third-party libraries should also be used.
In some 32-bit systems, it may be possible to change the representation of time (e.g. ‘time_t’ in “C”) from a signed integer to an unsigned integer, thus extending the time range another 68 years to 2106. Times prior to the epoch of Jan 1, 1970 would no longer be supported, but that may be an acceptable compromise. The time library for your environment would need to be replaced with one that uses 32-bit unsigned integers. All calls to existing time functions would need to be replaced with the new functions, and of course tested thoroughly.
It may be feasible in some existing systems to store additional high-order time bits in flash memory. Each extra bit doubles the amount of time that can be represented, so adding a single bit would extend the time by another 68 years to 2106. Similar to above, this approach would require a new library of time-related functions, and all calls to the standard time functions would need to be replaced with the new versions and tested.
Another possibility is to consider the approach envisioned for Network Time Protocol version 5 (NTP). Version 4 of NTP uses 32 bits (unsigned) of seconds along with 32 bits of fractional seconds. This version will experience a wrap condition in the year 2036. Version 5 of NTP will likely use 64 bits of seconds and 64 bits of fractional seconds. Again similar to above, to use this approach for addressing Y2038 would require a new time-related function library to support this time format, as well as changes to existing code.
One website details an approach referred to as pivotal time, described here. This technique assumes the current time will wrap back to 1901, but is interpreted to mean +/- 68 years from the actual current date.
In new hardware designs, the hardware should always be designed to support time values larger than 32-bits, even if the CPU is 32-bits. This will make it easier to provide extended time range functionality.
Part of almost any Y2038 solution is that all source code should be checked for all uses of time in order to assure Y2038-compatibility. For example, in “C”, all instances of time_t and time-related functions should be carefully reviewed. For example, values of a 64-bit type time_t can inadvertently be cast or stored into 32-bit integers.
You might notice that using 64-bits to hold seconds is actually quite wasteful since the time represented by a 64-bit signed quantity of seconds is around 292 billion years, which is quite a few times the estimated age of the universe! Practically speaking, it would be much more useful for the 64 bits to represent a time value for the number of milliseconds or microseconds since an epoch. A 64-bit signed value in milliseconds can hold approx. +/- 292 million years, while a 64-bit signed value in microseconds can hold approx +/- 292,000 years.
It would also be convenient if the epoch were to be redefined as midnight on Jan. 1, 0000. However, since these types of modifications would require changing broadly established industry standards (not to mention even more extensive coding changes), such improvements will most likely not be broadly accepted.