May 10, 2019

How to Use Gamlss with Ggplot2

I was exploring Gamlss and seeing if I could plot the resulting models with ggplot2. While a gamlss model is not, strictly speaking, coercible to data.frame, nor is there a fortify method included, I wrote a quick method and am providing it here, gratis: fortify.gamlss <- function(gamlss.obj) { return(data.frame(x=c(1:length(gamlss.obj$y)), y=gamlss.obj$y)) }

I would appreciate it if those responsible would incorporate this into the tree. Many thanks!

March 26, 2019

How I wrote my own CI System

This evening, while playing with whereishasan, my upstream ISP connection went down. Diagnosing the problem, I had no idea -- all my tests were failing and I had no idea why -- unbound was fine -- it had the server in its cache, the local network was working fine, yet the remote host was frozen. So, I rebooted the router. Then waited, waited, waited, as it flushed its cache and decided to do its DHCP handshake. Then everything was fine -- I updated the location, and my tests passed again. To prevent this in the future, I whipped up a cronjob to run my unit tests and email me when they failed using sendEmail. Slotted it into the daily cron on my local server, ran a few tests and, happy it worked, I relaxed. Now to figure out how to make it run on push and kill the process if tests fail.

February 5, 2019

Substrings Working on sqlTime

Subject has the tl;dr. Here are the details. I wanted to be able to type sqlTime Madrid and get the local time. However, the actual argument I needed to use for this was Europe/Madrid. That's a bit annoying.

So, as with most of my passion projects, annoyance is the mother of invention. First things first, how would I handle this. Regular expressions came to mind. Shortly thereafter PCRE popped into my head. This library provides Perl-compatible regular expressions in C. It's open source and its license is acceptable. However, I determined it to be too heavy to incorporate for what is only implementing substring matching.

Then I found that postgres, which the system is built on, supports a plethora of functions for matching strings. Problem solved?

Perhaps not, I then tried the regex library from 4.4 BSD, which is to be found everywhere I'd use this setup. Again, it was overkill.

Finally, I had un ballon du rouge in me and went back to first principles. What did I aim to accomplish here? Essentially I wanted to allow the city name instead of having to specify the continent. Since the city name would certainly be in the timezone name, I needed a substring function. man -k substring on my system yielded strstr, strcasestr, strnstr, strcasestr_l(3) - locate a substring in a string. char *strcasestr(const char *big, const char *little); is the provided prototype for the case insensitive substring function; strstr is the case sensitive one. And the functions locates the first occurrence of the null-terminated string little in the null-terminated string big. and return a pointer to the start of the substring and null if it's not found. A few if statements later and sqlTime Madrid was returning the correct output. I then committed the code, updated the gist, wrote this post, and decided to get to bed. If you'd like to try it out, leave me your platform and I'll send you a binary.

January 15, 2019

How to know what time it is

I've been working on a world clock over the past week and I've finally got it to the point where I feel like I can release it. Sample runs follow and the source is linked to above:

 % ../sqlTime 
Africa/Abidjan, 00:00:00
Africa/Accra, 00:00:00
Africa/Addis_Ababa, 03:00:00
Africa/Algiers, 01:00:00
Africa/Asmara, 03:00:00
Africa/Asmera, 03:00:00
Africa/Bamako, 00:00:00
Africa/Bangui, 01:00:00
Africa/Banjul, 00:00:00
Africa/Bissau, 00:00:00
Africa/Blantyre, 02:00:00
Africa/Brazzaville, 01:00:00
Africa/Bujumbura, 02:00:00
Africa/Cairo, 02:00:00
Africa/Casablanca, 01:00:00
Africa/Ceuta, 01:00:00
Africa/Conakry, 00:00:00
Africa/Dakar, 00:00:00
Africa/Dar_es_Salaam, 03:00:00
Africa/Djibouti, 03:00:00
Africa/Douala, 01:00:00
Africa/El_Aaiun, 01:00:00
Africa/Freetown, 00:00:00
Africa/Gaborone, 02:00:00
Africa/Harare, 02:00:00
Africa/Johannesburg, 02:00:00
Africa/Juba, 03:00:00
Africa/Kampala, 03:00:00
Africa/Khartoum, 02:00:00
Africa/Kigali, 02:00:00
Africa/Kinshasa, 01:00:00
Africa/Lagos, 01:00:00
Africa/Libreville, 01:00:00
Africa/Lome, 00:00:00
Africa/Luanda, 01:00:00
Africa/Lubumbashi, 02:00:00
Africa/Lusaka, 02:00:00
Africa/Malabo, 01:00:00
Africa/Maputo, 02:00:00
Africa/Maseru, 02:00:00
Africa/Mbabane, 02:00:00
Africa/Mogadishu, 03:00:00
Africa/Monrovia, 00:00:00
Africa/Nairobi, 03:00:00
Africa/Ndjamena, 01:00:00
Africa/Niamey, 01:00:00
Africa/Nouakchott, 00:00:00
Africa/Ouagadougou, 00:00:00
Africa/Porto-Novo, 01:00:00
Africa/Sao_Tome, 01:00:00
Africa/Timbuktu, 00:00:00
Africa/Tripoli, 02:00:00
Africa/Tunis, 01:00:00
Africa/Windhoek, 02:00:00
America/Adak, -10:00:00
America/Anchorage, -09:00:00
America/Anguilla, -04:00:00
America/Antigua, -04:00:00
America/Araguaina, -03:00:00
America/Argentina/Buenos_Aires, -03:00:00
America/Argentina/Catamarca, -03:00:00
America/Argentina/ComodRivadavia, -03:00:00
America/Argentina/Cordoba, -03:00:00
America/Argentina/Jujuy, -03:00:00
America/Argentina/La_Rioja, -03:00:00
America/Argentina/Mendoza, -03:00:00
America/Argentina/Rio_Gallegos, -03:00:00
America/Argentina/Salta, -03:00:00
America/Argentina/San_Juan, -03:00:00
America/Argentina/San_Luis, -03:00:00
America/Argentina/Tucuman, -03:00:00
America/Argentina/Ushuaia, -03:00:00
America/Aruba, -04:00:00
America/Asuncion, -03:00:00
America/Atikokan, -05:00:00
America/Atka, -10:00:00
America/Bahia, -03:00:00
America/Bahia_Banderas, -06:00:00
America/Barbados, -04:00:00
America/Belem, -03:00:00
America/Belize, -06:00:00
America/Blanc-Sablon, -04:00:00
America/Boa_Vista, -04:00:00
America/Bogota, -05:00:00
America/Boise, -07:00:00
America/Buenos_Aires, -03:00:00
America/Cambridge_Bay, -07:00:00
America/Campo_Grande, -03:00:00
America/Cancun, -05:00:00
America/Caracas, -04:00:00
America/Catamarca, -03:00:00
America/Cayenne, -03:00:00
America/Cayman, -05:00:00
America/Chicago, -06:00:00
America/Chihuahua, -07:00:00
America/Coral_Harbour, -05:00:00
America/Cordoba, -03:00:00
America/Costa_Rica, -06:00:00
America/Creston, -07:00:00
America/Cuiaba, -03:00:00
America/Curacao, -04:00:00
America/Danmarkshavn, 00:00:00
America/Dawson, -08:00:00
America/Dawson_Creek, -07:00:00
America/Denver, -07:00:00
America/Detroit, -05:00:00
America/Dominica, -04:00:00
America/Edmonton, -07:00:00
America/Eirunepe, -05:00:00
America/El_Salvador, -06:00:00
America/Ensenada, -08:00:00
America/Fort_Nelson, -07:00:00
America/Fort_Wayne, -05:00:00
America/Fortaleza, -03:00:00
America/Glace_Bay, -04:00:00
America/Godthab, -03:00:00
America/Goose_Bay, -04:00:00
America/Grand_Turk, -05:00:00
America/Grenada, -04:00:00
America/Guadeloupe, -04:00:00
America/Guatemala, -06:00:00
America/Guayaquil, -05:00:00
America/Guyana, -04:00:00
America/Halifax, -04:00:00
America/Havana, -05:00:00
America/Hermosillo, -07:00:00
America/Indiana/Indianapolis, -05:00:00
America/Indiana/Knox, -06:00:00
America/Indiana/Marengo, -05:00:00
America/Indiana/Petersburg, -05:00:00
America/Indiana/Tell_City, -06:00:00
America/Indiana/Vevay, -05:00:00
America/Indiana/Vincennes, -05:00:00
America/Indiana/Winamac, -05:00:00
America/Indianapolis, -05:00:00
America/Inuvik, -07:00:00
America/Iqaluit, -05:00:00
America/Jamaica, -05:00:00
America/Jujuy, -03:00:00
America/Juneau, -09:00:00
America/Kentucky/Louisville, -05:00:00
America/Kentucky/Monticello, -05:00:00
America/Knox_IN, -06:00:00
America/Kralendijk, -04:00:00
America/La_Paz, -04:00:00
America/Lima, -05:00:00
America/Los_Angeles, -08:00:00
America/Louisville, -05:00:00
America/Lower_Princes, -04:00:00
America/Maceio, -03:00:00
America/Managua, -06:00:00
America/Manaus, -04:00:00
America/Marigot, -04:00:00
America/Martinique, -04:00:00
America/Matamoros, -06:00:00
America/Mazatlan, -07:00:00
America/Mendoza, -03:00:00
America/Menominee, -06:00:00
America/Merida, -06:00:00
America/Metlakatla, -09:00:00
America/Mexico_City, -06:00:00
America/Miquelon, -03:00:00
America/Moncton, -04:00:00
America/Monterrey, -06:00:00
America/Montevideo, -03:00:00
America/Montreal, -05:00:00
America/Montserrat, -04:00:00
America/Nassau, -05:00:00
America/New_York, -05:00:00
America/Nipigon, -05:00:00
America/Nome, -09:00:00
America/Noronha, -02:00:00
America/North_Dakota/Beulah, -06:00:00
America/North_Dakota/Center, -06:00:00
America/North_Dakota/New_Salem, -06:00:00
America/Ojinaga, -07:00:00
America/Panama, -05:00:00
America/Pangnirtung, -05:00:00
America/Paramaribo, -03:00:00
America/Phoenix, -07:00:00
America/Port-au-Prince, -05:00:00
America/Port_of_Spain, -04:00:00
America/Porto_Acre, -05:00:00
America/Porto_Velho, -04:00:00
America/Puerto_Rico, -04:00:00
America/Punta_Arenas, -03:00:00
America/Rainy_River, -06:00:00
America/Rankin_Inlet, -06:00:00
America/Recife, -03:00:00
America/Regina, -06:00:00
America/Resolute, -06:00:00
America/Rio_Branco, -05:00:00
America/Rosario, -03:00:00
America/Santa_Isabel, -08:00:00
America/Santarem, -03:00:00
America/Santiago, -03:00:00
America/Santo_Domingo, -04:00:00
America/Sao_Paulo, -02:00:00
America/Scoresbysund, -01:00:00
America/Shiprock, -07:00:00
America/Sitka, -09:00:00
America/St_Barthelemy, -04:00:00
America/St_Johns, -03:30:00
America/St_Kitts, -04:00:00
America/St_Lucia, -04:00:00
America/St_Thomas, -04:00:00
America/St_Vincent, -04:00:00
America/Swift_Current, -06:00:00
America/Tegucigalpa, -06:00:00
America/Thule, -04:00:00
America/Thunder_Bay, -05:00:00
America/Tijuana, -08:00:00
America/Toronto, -05:00:00
America/Tortola, -04:00:00
America/Vancouver, -08:00:00
America/Virgin, -04:00:00
America/Whitehorse, -08:00:00
America/Winnipeg, -06:00:00
America/Yakutat, -09:00:00
America/Yellowknife, -07:00:00
Antarctica/Casey, 08:00:00
Antarctica/Davis, 07:00:00
Antarctica/DumontDUrville, 10:00:00
Antarctica/Macquarie, 11:00:00
Antarctica/Mawson, 05:00:00
Antarctica/McMurdo, 13:00:00
Antarctica/Palmer, -03:00:00
Antarctica/Rothera, -03:00:00
Antarctica/South_Pole, 13:00:00
Antarctica/Syowa, 03:00:00
Antarctica/Troll, 00:00:00
Antarctica/Vostok, 06:00:00
Arctic/Longyearbyen, 01:00:00
Asia/Aden, 03:00:00
Asia/Almaty, 06:00:00
Asia/Amman, 02:00:00
Asia/Anadyr, 12:00:00
Asia/Aqtau, 05:00:00
Asia/Aqtobe, 05:00:00
Asia/Ashgabat, 05:00:00
Asia/Ashkhabad, 05:00:00
Asia/Atyrau, 05:00:00
Asia/Baghdad, 03:00:00
Asia/Bahrain, 03:00:00
Asia/Baku, 04:00:00
Asia/Bangkok, 07:00:00
Asia/Barnaul, 07:00:00
Asia/Beirut, 02:00:00
Asia/Bishkek, 06:00:00
Asia/Brunei, 08:00:00
Asia/Calcutta, 05:30:00
Asia/Chita, 09:00:00
Asia/Choibalsan, 08:00:00
Asia/Chongqing, 08:00:00
Asia/Chungking, 08:00:00
Asia/Colombo, 05:30:00
Asia/Dacca, 06:00:00
Asia/Damascus, 02:00:00
Asia/Dhaka, 06:00:00
Asia/Dili, 09:00:00
Asia/Dubai, 04:00:00
Asia/Dushanbe, 05:00:00
Asia/Famagusta, 02:00:00
Asia/Gaza, 02:00:00
Asia/Harbin, 08:00:00
Asia/Hebron, 02:00:00
Asia/Ho_Chi_Minh, 07:00:00
Asia/Hong_Kong, 08:00:00
Asia/Hovd, 07:00:00
Asia/Irkutsk, 08:00:00
Asia/Istanbul, 03:00:00
Asia/Jakarta, 07:00:00
Asia/Jayapura, 09:00:00
Asia/Jerusalem, 02:00:00
Asia/Kabul, 04:30:00
Asia/Kamchatka, 12:00:00
Asia/Karachi, 05:00:00
Asia/Kashgar, 06:00:00
Asia/Kathmandu, 05:45:00
Asia/Katmandu, 05:45:00
Asia/Khandyga, 09:00:00
Asia/Kolkata, 05:30:00
Asia/Krasnoyarsk, 07:00:00
Asia/Kuala_Lumpur, 08:00:00
Asia/Kuching, 08:00:00
Asia/Kuwait, 03:00:00
Asia/Macao, 08:00:00
Asia/Macau, 08:00:00
Asia/Magadan, 11:00:00
Asia/Makassar, 08:00:00
Asia/Manila, 08:00:00
Asia/Muscat, 04:00:00
Asia/Nicosia, 02:00:00
Asia/Novokuznetsk, 07:00:00
Asia/Novosibirsk, 07:00:00
Asia/Omsk, 06:00:00
Asia/Oral, 05:00:00
Asia/Phnom_Penh, 07:00:00
Asia/Pontianak, 07:00:00
Asia/Pyongyang, 09:00:00
Asia/Qatar, 03:00:00
Asia/Qyzylorda, 06:00:00
Asia/Rangoon, 06:30:00
Asia/Riyadh, 03:00:00
Asia/Saigon, 07:00:00
Asia/Sakhalin, 11:00:00
Asia/Samarkand, 05:00:00
Asia/Seoul, 09:00:00
Asia/Shanghai, 08:00:00
Asia/Singapore, 08:00:00
Asia/Srednekolymsk, 11:00:00
Asia/Taipei, 08:00:00
Asia/Tashkent, 05:00:00
Asia/Tbilisi, 04:00:00
Asia/Tehran, 03:30:00
Asia/Tel_Aviv, 02:00:00
Asia/Thimbu, 06:00:00
Asia/Thimphu, 06:00:00
Asia/Tokyo, 09:00:00
Asia/Tomsk, 07:00:00
Asia/Ujung_Pandang, 08:00:00
Asia/Ulaanbaatar, 08:00:00
Asia/Ulan_Bator, 08:00:00
Asia/Urumqi, 06:00:00
Asia/Ust-Nera, 10:00:00
Asia/Vientiane, 07:00:00
Asia/Vladivostok, 10:00:00
Asia/Yakutsk, 09:00:00
Asia/Yangon, 06:30:00
Asia/Yekaterinburg, 05:00:00
Asia/Yerevan, 04:00:00
Atlantic/Azores, -01:00:00
Atlantic/Bermuda, -04:00:00
Atlantic/Canary, 00:00:00
Atlantic/Cape_Verde, -01:00:00
Atlantic/Faeroe, 00:00:00
Atlantic/Faroe, 00:00:00
Atlantic/Jan_Mayen, 01:00:00
Atlantic/Madeira, 00:00:00
Atlantic/Reykjavik, 00:00:00
Atlantic/South_Georgia, -02:00:00
Atlantic/St_Helena, 00:00:00
Atlantic/Stanley, -03:00:00
Australia/ACT, 11:00:00
Australia/Adelaide, 10:30:00
Australia/Brisbane, 10:00:00
Australia/Broken_Hill, 10:30:00
Australia/Canberra, 11:00:00
Australia/Currie, 11:00:00
Australia/Darwin, 09:30:00
Australia/Eucla, 08:45:00
Australia/Hobart, 11:00:00
Australia/LHI, 11:00:00
Australia/Lindeman, 10:00:00
Australia/Lord_Howe, 11:00:00
Australia/Melbourne, 11:00:00
Australia/NSW, 11:00:00
Australia/North, 09:30:00
Australia/Perth, 08:00:00
Australia/Queensland, 10:00:00
Australia/South, 10:30:00
Australia/Sydney, 11:00:00
Australia/Tasmania, 11:00:00
Australia/Victoria, 11:00:00
Australia/West, 08:00:00
Australia/Yancowinna, 10:30:00
Brazil/Acre, -05:00:00
Brazil/DeNoronha, -02:00:00
Brazil/East, -02:00:00
Brazil/West, -04:00:00
CST6CDT, -06:00:00
Canada/Atlantic, -04:00:00
Canada/Central, -06:00:00
Canada/Eastern, -05:00:00
Canada/Mountain, -07:00:00
Canada/Newfoundland, -03:30:00
Canada/Pacific, -08:00:00
Canada/Saskatchewan, -06:00:00
Canada/Yukon, -08:00:00
Chile/Continental, -03:00:00
Chile/EasterIsland, -05:00:00
EST5EDT, -05:00:00
Egypt, 02:00:00
Etc/GMT, 00:00:00
Etc/GMT+0, 00:00:00
Etc/GMT+1, -01:00:00
Etc/GMT+10, -10:00:00
Etc/GMT+11, -11:00:00
Etc/GMT+12, -12:00:00
Etc/GMT+2, -02:00:00
Etc/GMT+3, -03:00:00
Etc/GMT+4, -04:00:00
Etc/GMT+5, -05:00:00
Etc/GMT+6, -06:00:00
Etc/GMT+7, -07:00:00
Etc/GMT+8, -08:00:00
Etc/GMT+9, -09:00:00
Etc/GMT-0, 00:00:00
Etc/GMT-1, 01:00:00
Etc/GMT-10, 10:00:00
Etc/GMT-11, 11:00:00
Etc/GMT-12, 12:00:00
Etc/GMT-13, 13:00:00
Etc/GMT-14, 14:00:00
Etc/GMT-2, 02:00:00
Etc/GMT-3, 03:00:00
Etc/GMT-4, 04:00:00
Etc/GMT-5, 05:00:00
Etc/GMT-6, 06:00:00
Etc/GMT-7, 07:00:00
Etc/GMT-8, 08:00:00
Etc/GMT-9, 09:00:00
Etc/GMT0, 00:00:00
Etc/Greenwich, 00:00:00
Etc/UCT, 00:00:00
Etc/UTC, 00:00:00
Etc/Universal, 00:00:00
Etc/Zulu, 00:00:00
Europe/Amsterdam, 01:00:00
Europe/Andorra, 01:00:00
Europe/Astrakhan, 04:00:00
Europe/Athens, 02:00:00
Europe/Belfast, 00:00:00
Europe/Belgrade, 01:00:00
Europe/Berlin, 01:00:00
Europe/Bratislava, 01:00:00
Europe/Brussels, 01:00:00
Europe/Bucharest, 02:00:00
Europe/Budapest, 01:00:00
Europe/Busingen, 01:00:00
Europe/Chisinau, 02:00:00
Europe/Copenhagen, 01:00:00
Europe/Dublin, 00:00:00
Europe/Gibraltar, 01:00:00
Europe/Guernsey, 00:00:00
Europe/Helsinki, 02:00:00
Europe/Isle_of_Man, 00:00:00
Europe/Istanbul, 03:00:00
Europe/Jersey, 00:00:00
Europe/Kaliningrad, 02:00:00
Europe/Kiev, 02:00:00
Europe/Kirov, 03:00:00
Europe/Lisbon, 00:00:00
Europe/Ljubljana, 01:00:00
Europe/London, 00:00:00
Europe/Luxembourg, 01:00:00
Europe/Madrid, 01:00:00
Europe/Malta, 01:00:00
Europe/Mariehamn, 02:00:00
Europe/Minsk, 03:00:00
Europe/Monaco, 01:00:00
Europe/Moscow, 03:00:00
Europe/Nicosia, 02:00:00
Europe/Oslo, 01:00:00
Europe/Paris, 01:00:00
Europe/Podgorica, 01:00:00
Europe/Prague, 01:00:00
Europe/Riga, 02:00:00
Europe/Rome, 01:00:00
Europe/Samara, 04:00:00
Europe/San_Marino, 01:00:00
Europe/Sarajevo, 01:00:00
Europe/Saratov, 04:00:00
Europe/Simferopol, 03:00:00
Europe/Skopje, 01:00:00
Europe/Sofia, 02:00:00
Europe/Stockholm, 01:00:00
Europe/Tallinn, 02:00:00
Europe/Tirane, 01:00:00
Europe/Tiraspol, 02:00:00
Europe/Ulyanovsk, 04:00:00
Europe/Uzhgorod, 02:00:00
Europe/Vaduz, 01:00:00
Europe/Vatican, 01:00:00
Europe/Vienna, 01:00:00
Europe/Vilnius, 02:00:00
Europe/Volgograd, 04:00:00
Europe/Warsaw, 01:00:00
Europe/Zagreb, 01:00:00
Europe/Zaporozhye, 02:00:00
Europe/Zurich, 01:00:00
GB-Eire, 00:00:00
GMT+0, 00:00:00
GMT-0, 00:00:00
Greenwich, 00:00:00
Hongkong, 08:00:00
Iceland, 00:00:00
Indian/Antananarivo, 03:00:00
Indian/Chagos, 06:00:00
Indian/Christmas, 07:00:00
Indian/Cocos, 06:30:00
Indian/Comoro, 03:00:00
Indian/Kerguelen, 05:00:00
Indian/Mahe, 04:00:00
Indian/Maldives, 05:00:00
Indian/Mauritius, 04:00:00
Indian/Mayotte, 03:00:00
Indian/Reunion, 04:00:00
Israel, 02:00:00
Jamaica, -05:00:00
Japan, 09:00:00
Kwajalein, 12:00:00
Libya, 02:00:00
MST7MDT, -07:00:00
Mexico/BajaNorte, -08:00:00
Mexico/BajaSur, -07:00:00
Mexico/General, -06:00:00
NZ-CHAT, 13:45:00
Navajo, -07:00:00
PST8PDT, -08:00:00
Pacific/Apia, 14:00:00
Pacific/Auckland, 13:00:00
Pacific/Bougainville, 11:00:00
Pacific/Chatham, 13:45:00
Pacific/Chuuk, 10:00:00
Pacific/Easter, -05:00:00
Pacific/Efate, 11:00:00
Pacific/Enderbury, 13:00:00
Pacific/Fakaofo, 13:00:00
Pacific/Fiji, 12:00:00
Pacific/Funafuti, 12:00:00
Pacific/Galapagos, -06:00:00
Pacific/Gambier, -09:00:00
Pacific/Guadalcanal, 11:00:00
Pacific/Guam, 10:00:00
Pacific/Honolulu, -10:00:00
Pacific/Johnston, -10:00:00
Pacific/Kiritimati, 14:00:00
Pacific/Kosrae, 11:00:00
Pacific/Kwajalein, 12:00:00
Pacific/Majuro, 12:00:00
Pacific/Marquesas, -09:30:00
Pacific/Midway, -11:00:00
Pacific/Nauru, 12:00:00
Pacific/Niue, -11:00:00
Pacific/Norfolk, 11:00:00
Pacific/Noumea, 11:00:00
Pacific/Pago_Pago, -11:00:00
Pacific/Palau, 09:00:00
Pacific/Pitcairn, -08:00:00
Pacific/Pohnpei, 11:00:00
Pacific/Ponape, 11:00:00
Pacific/Port_Moresby, 10:00:00
Pacific/Rarotonga, -10:00:00
Pacific/Saipan, 10:00:00
Pacific/Samoa, -11:00:00
Pacific/Tahiti, -10:00:00
Pacific/Tarawa, 12:00:00
Pacific/Tongatapu, 13:00:00
Pacific/Truk, 10:00:00
Pacific/Wake, 12:00:00
Pacific/Wallis, 12:00:00
Pacific/Yap, 10:00:00
Poland, 01:00:00
Portugal, 00:00:00
Singapore, 08:00:00
Turkey, 03:00:00
US/Alaska, -09:00:00
US/Aleutian, -10:00:00
US/Arizona, -07:00:00
US/Central, -06:00:00
US/East-Indiana, -05:00:00
US/Eastern, -05:00:00
US/Hawaii, -10:00:00
US/Indiana-Starke, -06:00:00
US/Michigan, -05:00:00
US/Mountain, -07:00:00
US/Pacific, -08:00:00
US/Samoa, -11:00:00
Universal, 00:00:00
posixrules, -05:00:00

% ../sqlTime CSTa
Invalid timezone CSTa

% ../sqlTime Europe/Madrid
2019-01-15 10:00:50.570864

In other words, ¡hola EspaƱa!

January 8, 2019

Python API Wrapper for CurrencyStack

In my never-ending quest to make the web digestible by machine, I encountered currencystack on ProductHunt. I noticed they have a JSON API. I tweeted them offering my services. A rate was agreed upon, and a few hours later, it was done. And I have another line on my CV.

December 5, 2018

How to Fix SSL Validation Errors on Heroku

Over the past few weeks, we started getting errors in regards to SSL on heroku postgresql. So, we disabled it and our tests are happy again.

November 12, 2018

How to use SSL in Spring-boot and LetsEncrypt Easily

When developing Geonotes, I ran into the issue of Chrome not allowing non-HTTPS access to geolocation. The geonotes backend is Java, which generally implies that its robust, but needs to be tweaked a great deal for every use case -- read, not something I enjoy doing. After a brief look at available workarounds and trying a few out, I wanted to pull my hair out, but found there wasn't much left to pull. In the back of my mind somewhere, I recalled there was a way to set up an HTTPS-to-HTTP proxy, thus avoiding the need to mess with keytool and the rest of it, stunnel. Just needed to add a cronjob for certbot to renew certificates and Openssl commands to convert the issued certificate to one that the J2ee middleware likes. Without further ado, then.

Stunnel creates an proxy server on the localhost and handles the SSL to plaintext conversion. Indeed, the configuration is cake:

pid = /home/ec2-user/postgisweb/stunnel.pid
cert = /home/ec2-user/postgisweb/ssl.pem

[geonotes]
accept = 0.0.0.0:8443
connect = 127.0.0.1:8080

8080 is my HTTP port, and I want to run SSL on 8443. The wildcard IP is necessary because we want stunnel to listen on all IP addresses on the server, but want HTTP allowed only on localhost (else there's no point in SSL in the first place). The other interesting part is that ssl.pem is constructed using cat /usr/local/etc/letsencrypt/live/hasan.d8u.us/privkey.pem /usr/local/etc/letsencrypt/live/hasan.d8u.us/fullchain.pem | tee append ~ec2-user/postgisweb/ssl.pem. Stick the command in a cron job and have it run often -- I have mine set to every 3 hours.

We verify our work, by pointing our browser to port 8443 and checking if there are SSL issues. There are not. And we're set.

October 18, 2018

How to Speed Up Diffbot

Diffbot is an AI startup that provides knowledge as a service to power intelligent applications. As with most such services, its reach (by default) exceeds its grasp in terms of performance. We use it to clean up articles that are added to our system, as do a number of others. We found it slow -- indeed when I took it out, processing time improved by almost 50%. In this piece, I will share what the magic parameters I found are to accomplish this. Hopefully, you will also find it useful.
I stumbled upon a support article entitled Improving API Response Times, from which these parameters are sourced. Setting the discussion parameter to false will remove parsing of any comments or reviews. The second (and key) use case is the paging parameter. Setting this to false downloads only the first page of a multipage article.
A site like Fiskkit can not use the first page of a multipage article, but your use case may not require it. Enjoy, and if you'd like to hire me, I'm always available for contract work.

September 10, 2018

How to Sort Java-generated JSON

I was looking for a way to sort JSON by key. Why? It's easier to read and locate if you know it's order is consistent. I'm using Jackson as my parser, in Spring boot. There are several ways I'm able to see to accomplish this:
  • Spring has an application.properties/application.yml setting -- http.mappers.json-sort-keys -- which does not work with Jackson.
  • Jackson's ObjectMapper may be configured to sort keys using the ORDER_MAP_ENTRIES_BY_KEYS property. This worked, but there has got to be an easier way to dot this, which is...
  • Java itself has a TreeMap, whose default key comparator is lexical, meaning that you get this functionality out of the box. This is the approach I ended up using.

February 12, 2018

How States Voted in 2016 Compared to Their Contribution to the US GDP

The other day, I got into a spat with someone on Facebook who swore up and down that the American populace votes in accordance with their economic interest, but when I asked for proof, they pointed to state-by-state growth rates. They've since blocked me, but I was able to generate a plot to prove they do not.