Introduction

Easter passed by not to long ago and I found out that Easter day is determined by the phase of the moon. I think this is really interesting and the Wikipedia page has a lot of information. It also has an algorithm that lets you calculate the day of Easter.

I wanted to do something with this and I ended up making a web app that will tell you if it’s Easter. I was planning to spend some time learning about cloud services and writing apps utilizing them heavily so this was perfect as the app I could build for this other project.

The Easter Day Algorithm

For calculating Easter day, I used the Anonymous Gregorian algorithm as described with the New Scientist modifications. It’s very straight forward and works very well.

def easter_date(year: int) -> date:
    a = year % 19
    b = year // 100
    c = year % 100
    d = b // 4
    e = b % 4
    g = ((8 * b) + 13) // 25
    h = ((19 * a) + b - d - g + 15) % 30
    i = c // 4
    k = c % 4
    l = (32 + (2 * e) + (2 * i) - h - k) % 7
    m = ((a + (11 * h)) + (19 * i)) // 433
    n = (h + l - (7 * m) + 90) // 25 # month
    p = (h + l - (7 * m) + (33 * n) + 19) % 32 # day

    return date(year, n, p)

The algorithm uses integer division with truncation which needs to be taken into account with Python by using // instead of the float / operator.

The Web App

I decided to use Flask which has a lot of nice features built in. Like integration with Jinja2. It’s still lightweight and stays out of your way which is also very nice. Epically since this is a since page app, that won’t use a database, and doesn’t have a login system. Flask got out of my way and made it very easy to build the app.

I relied heavily on Pallets Flask documentation for learning how to build not only a web app, but building it with Flask.

Design

The app is a single page that will show a different message based whether it’s Easter or not.

Not Easter

When it’s not Easter, the page will show a picture of a sad bunny. It will also state what day Easter will be on.

Is Easter

When it’s Easter, the page will show a happy bunny and say it’s Easter.

Timezones

Since anyone anywhere in the world could visit the website it’s very important to account for the visitors timezone. It can be a different day in in the visitor’s timezone versus the server’s. This can throw telling the visitor if it’s Easter day.

I found out web browsers don’t send the visitor’s timezone in a header! They send all kinds of the information about the browser but timezone isn’t there. I looked at ways to get the visitor’s timezone and I found 3 methods.

Methods

Ask the visitor

This doesn’t work for me because I don’t want to have visitor interaction and it means the visitor has to either correct from the default or specify before they can use the site. It’s just not a good experience for this project.

Send the timezone via Javascript

This isn’t a terrible idea and most people recommend using Moment.js for any time handling in Javascript. However, this isn’t going to work either. The browser has to load the site then send the request to the server which then can calculate whether it’s Easter for the visitor.

I’d have to have the Javascript reload the page while passing the timezone. This isn’t ideal…

Alternatively, I could have the site be an Ajax request to the back end which would return the information for the browser to update the page view. I didn’t want to do this because it would require a public service for querying if it’s Easter. I don’t want to expose a service like that and only want the information to be accessible by visiting the website directly. Even with protections like origin requests, I didn’t want to split the back end like this.

Also, it would result in a blank page or some kind of splash page before loading the site content. This is fine for some sites but with how simple this is, I didn’t think it would be a good experience.

Geo IP Location

This is what I ended up using. While it’s not perfect, it is fully transparent to the visitor.

I’m using ipgeolocation which has a very nice API and includes timezone data. Not just timezone data but the UTC offset in hours which makes it even easier because I need the offset to adjust the time. Otherwise, I’d have to lookup the timezone name, such as America/New_York, to get the offset.

The biggest issue is VPNs. If someone is using a VPN the timezone detected from their IP address may not match where they really are. I’m not too concerned about this and in the future maybe I’ll add a way for visitors to manually adjust the timezone. Also, VPN users are used to this type of situation. Changing your location for streaming services is one of the marketing points pushed by VPN companies.

Cloud System

Part of this project was using cloud systems and the more I looked into them, the more I realized they’re not right for this project. Not only that, the cost was a bit more than I wanted to spend.

I was planning to use Azure App Service to host the app. I like that it automatically checks out the source code, builds and runs a Linux container for you. I wouldn’t have to manage containers or servers. I’d pair this with Blob storage and use that as a mount point into the container. I’d need to do this because some assets (pictures) are not distributed with the source and need to be added outside of the normal App Service deployment system.

I also wanted to use Cloudflare for DDoS protection but ended up not because it really isn’t necessary. Azure provides DDoS protection, TLS certificate management, and reverse proxy.

That said, instead of using Azure like I was planning, I deployed the app to this server that also runs my blog and the blog search service. It was a no additional hosting cost solution and the decision really came down to cost more than anything.

Costs of the project

While my hosting cost is $0 because I’m using a VPS I’m already paying for, I did have to spend some money on this project.

WhatPrice
Domain name$15.50
Bunny pictures$22
Total$37.50

This isn’t quite true, because I bought to .us domains but I really only need one.

Culmination

Finally, the site unveiled! Is it Easter? is up and running. The source code is also up. The Readme file has more information about the technical design and optimizations around using 3rd party services. This post is really just an introduction and not a deep technical dive, if you haven’t noticed.

Conclusion

I learned a lot about we apps and even more about CSS. Developing the app I probably spent three quarters of the time just trying to get the layout and look of the site to be semi decent.

I also learned a lot about cloud hosting and understanding what they excel at and when they aren’t the right solution. While cloud services were one goal of the project I feel like I got what I wanted out of the research I put into them. I may not have gotten hands on knowledge of doing a deployment, but I came away with a decent high level understanding of the process.

Ultimately, this was a for fun and learning project. There isn’t any utility in the website. If you put “when is easter” into Google it will give you the date. Very few people are going actually need or go to my website and that’s okay. I went into this project knowing this isn’t some ground breaking or world changing this. Fortunately, I was able to get what I wanted out of this and I’m satisfied.