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.

Android: Install ADB drivers for any device without OEM drivers

Figure 1. Android Robot

Figure 1. Android Robot

Well, I started my Android development on a Samsung I9100 Galaxy S II. I never had any trouble getting ADB to work on Microsoft Windows since I had the drivers from Samsung which was already installed due to my previous Cyanogenmod installation process. Afterwards, I received a Nexus 7 and a bit latter a Nexus 5 which became my primary development device of choice. Google did a good job by providing ADB drivers for All Nexus devices inside the SDK or as a small separate download on Android Developers website which was very easy to install. The trouble began when my development process involved testing my applications and games on devices other than Nexus ones I had. For some manufacturers I was never able to find the drivers. Finding the correct driver for each device was a huge pain until I found a solution that became a remedy for all my troubles getting ADB to work with any Android device, even without the OEM drivers. It even became my preferred alternative to manufacturer’s provided ADB drivers for all my other devices till this day, since I hate the bloat-ware and useless crap they provide along with their drivers which is inevitable to install anyway.

In the rest of this post I’m going to share my easy solution with you:

[Read More...]

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 1108, 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...]

Get nFringe to Work with Visual Studio 2012

As you’ve noticed there’s still no official support for Microsoft Visual Studio 2012 in recent Pixel Mine nFringe releases. While ago I came across an awesome forum post at Epic Games Forums which describs a simple process of getting nFringe to work with VS2012. Since then I’ve used it in my day to day development tasks and I had no difficulties at all using it. And damn, it’s pretty stable despite the fact that not officially supported by Pixel Mine. Even nFringe version 1.1 which I’ve tested is playing nice with VS2012.

The only prerequisite that you need is your previous VS2010 + nFringe installation to obtain some files from it. Once you’ve acquired these files you don’t need VS2010 or nFringe installer for further installations.

1. Open Windows Command Prompt (cmd.exe) and run the following commands:

> xcopy /E "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Pixel Mine" "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\"
> xcopy /E "C:\Program Files (x86)\Microsoft Visual Studio 10.0\UnrealScript" "C:\Program Files (x86)\Microsoft Visual Studio 11.0\"

2. Open up extension.vsixmanifest in Notepad or your favorite editor and change VisualStudio Version to 11 (Note: In the following path change 1.1 with your nfringe version, e.g. 1.2).

> notepad "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\Pixel Mine nFringe (UnrealScript)\1.1\extension.vsixmanifest"
extension.vsixmanifest
    <InstalledByMsi>true</InstalledByMsi>
    <SupportedProducts>
      <VisualStudio Version="11.0">

3. Run the following command to register nFringe extension in Visual Studio 2012:

> "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe" /setup

4. Finally, you need to re-validate your nFringe license in VS2012.

Happy coding ;)

Windows 8, Install .NET Framework 2.0 - 3.5 Offline

Well, I’ve failed to install .NET Framework 2.0/3.5 in Windows 8 using Program and Features in Control Panel, which I need for an older project I’ve done long ago. But I came across an easy solution which did the trick.

In Windows Command Prompt (cmd.exe) or Run dialog, enter the following command and hit Enter:

> Dism /online /enable-feature /featurename:NetFx3 /All /Source❌\sources\sxs /LimitAccess

Replace x: with path of your Windows 8 installation DVD.

  • Note: You have to run cmd.exe as Administrator in order for this to work!