Gregorian / Jalali (a.k.a. Persian Calendar) Date Conversion in C++ using boost::locale

Well, anyone who has ever developed a C++ game or application with Gregorian to Jalali date conversion (or, vice versa) requirement is well aware of the hurdles of doing such a task. I, for one, have been maintaining my own cross-platform C++ library for almost two decades now, with occasional bugs coming up from time to time.

Recently, I have been playing with boost::locale (developed by Artyom Beilis and contributed to Boost project) a bit more in order to utilize it in a personal project called Barandazstorm, a home-grown social media analysis tool. Browsing the docs, I noticed the following example which does not even compile on my compiler:

boost::locale Gregorian to Hebrew date conversion example
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
using namespace boost::locale;
using namespace boost::locale::period;
generator gen;
// Create locales with Hebrew and Gregorian (default) calendars.
std::locale l_hebrew=gen("en_US.UTF-8@calendar=hebrew");
std::locale l_gregorian=gen("en_US.UTF-8");
// Create a Gregorian date from fields
date_time greg(year(2010) + february() + day(5),l_gregorian);
// Assign a time point taken from the Gregorian date to date_time with
// the Hebrew calendar
date_time heb(greg.time(),l_hebrew);
// Now we can query the year.
std::cout << "Hebrew year is " << heb / year << std::endl;

So, I tried to make a guess and replaced the en_US.UTF-8@calendar=hebrew part with en_US.UTF-8@calendar=jalali which didn’t work. But, on the second try replacing that with en_US.UTF-8@calendar=persian actually worked! Which is sheer delight; due to the fact that now I found a solution to convert dates between both calendars as efortless as techonologies such as .NET in C++:

Two-way Gregorian / Jalali date conversion using boost::locale
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/**
* @file
* @author  Mamadou Babaei <info@babaei.net>
* @version 0.1.0
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 Mamadou Babaei
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @section DESCRIPTION
*
* Two-way Gregorian / Jalali date conversion using boost::locale example
*/

#include <iomanip>
#include <iostream>
#include <cstdlib>
#include <boost/locale.hpp>

void from_gregorian_to_jalali()
{
    boost::locale::generator generator;

    std::locale locale_gregorian = generator("en_US.UTF-8");
    std::locale locale_jalali = generator("en_US.UTF-8@calendar=persian");

    boost::locale::date_time gregorian(
            boost::locale::period::year(2020)
            + boost::locale::period::february()
            + boost::locale::period::day(25),
            locale_gregorian);

    boost::locale::date_time jalali(gregorian.time(), locale_jalali);

    std::cout << "Persian date is " << jalali / boost::locale::period::year()
            << "/" << std::setfill('0') << std::setw(2)
            << (jalali / boost::locale::period::month()) + 1
            << "/" << std::setfill('0') << std::setw(2)
            << jalali / boost::locale::period::day()
            << "." << std::endl;
}

void from_jalali_to_gregorian()
{
    boost::locale::generator generator;

    std::locale locale_gregorian = generator("en_US.UTF-8");
    std::locale locale_jalali = generator("en_US.UTF-8@calendar=persian");

    boost::locale::date_time jalali(
            boost::locale::period::year(1398)
            + boost::locale::period::month(11)
            + boost::locale::period::day(06),
            locale_jalali);

    boost::locale::date_time gregorian(jalali.time(), locale_gregorian);

    std::cout << "Gregorian date is " << gregorian / boost::locale::period::year()
            << "/" << std::setfill('0') << std::setw(2)
            << (gregorian / boost::locale::period::month()) + 1
            << "/" << std::setfill('0') << std::setw(2)
            << gregorian / boost::locale::period::day()
            << "." << std::endl;
}

int main()
{
    from_gregorian_to_jalali();
    from_jalali_to_gregorian();

    return EXIT_SUCCESS;
}

On a side note, for the above code to work your boost::locale libraries has to be built with ICU support; otherwise boost::locale throws an exception. On most Linux or BSD distros this is the default when you install Boost libraries from your distro’s package manager. On Windows, it requires a bit of effort if you are trying to build Boost binaries yourself, which is another story for another time.

I did test the above code on FreeBSD, Linux, and Microsoft Windows, using MSVC, GCC, LLVM/Clang, and MinGW, and it’s working as expected on all of these platforms.

Book Review: Application Development with Qt Creator - Second Edition

Almost three weeks ago I received a review request from one of the Packt Publishing staffs to review Application Development with Qt Creator, 2nd Edition written by Ray Rischpater which has been recently published by Packt Publishing. Since I’ve been developing cross platform Qt (cute, often mispronounced as Q-T cue-tee) applications from Qt 4 era back in 2008 – when Qt Creator was not around yet and the project was running by Trolltech at the time – and a handful of Qt Quick mobile applications over the past two years, I consider myself eligible enough to write a brief review on it. So, I was provided with a review copy and after reading it cover to cover, my thoughts on the book are as follows.

Application Development with Qt Creator, 2nd Edition

Application Development with Qt Creator, 2nd Edition

[Read More...]

Write Your Own Cross-Platform Cryptographic Library

Previously I’ve described the process of building Crypto++ on both FreeBSD and Windows using the GCC, MinGW and VC++ compilers.

Now, we want to develop our own cross-platform cryptographic wrapper library around Crypto++. I’ve already uploaded the full source code to GitHub. You can find the link to the code on GitHub at the end of this article.

Before you proceed, you have to build the Crypto++ library as I mentioned earlier here.

[Read More...]

How to Build C++ Cryptographic Library, Crypto++

Crypto++ is an awesome free and open source C++ class library of cryptographic algorithms and schemes which fully supports 32-bit and 64-bit architectures for many major operating systems, including FreeBSD, Linux, Solaris, Windows, Mac OS X and iOS. Currently, Crypto++ officially supports the following compilers:

  • MSVC 6.0 - 2010
  • GCC 3.3 - 4.5
  • C++Builder 2010
  • Intel C++ Compiler 9 - 11.1
  • Sun Studio 12u1, Express 11/08, Express 06/10

The latest version at the time of this writing is 5.6.1.

In spite of the power that Crypto++ offers, building and using it can be a little bit tricky. In the following we will describe the process of building Crypto++ on both FreeBSD and Windows using the GCC, MinGW and VC++ compilers.

[Read More...]

Should I Check if a Pointer Is NULL Before Deleting It?

Most of the time I see some C++ programmers who check if a pointer is NULL before deleting it.

if (ptr != NULL) {
    delete ptr;
    ptr = NULL;
}

Well, according to C++03 [ISO/IEC IS 14882:2003] ยง5.3.5/2 which explicitly states:

…if the value of the operand of delete is the null pointer the operation has no effect.

Therefore, deleting a NULL pointer has no effect (if the deallocation function is one supplied in the standard library), so it is not necessary to check for a NULL pointer before calling delete.

delete ptr;
ptr = NULL;
  • Note: Keep in mind that deleting a void* pointer results in undefined behavior whether it’s NULL or not.