4
\$\begingroup\$

I've written a small script, which calculates hours since the birth. I ask use about how old they are in years, months and day. I show them approximately how many hours they have lived. Below is the code.

Please tell me how can I improve it, in terms of algorithms, time/date calculation, UX, and python best practices.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
File: ageinhours.py
Author: Santosh Kumar
Github: @santosh
Description: Calculate age in hours.
"""

import sys
try:
    from PySide import QtGui, QtCore
except ModuleNotFoundError:
    from PySide2.QtWidgets import QtGui
    from PySide2 import QtCore

class AgeInHours(QtGui.QMainWindow):
    """The main window of AgeInHours"""
    def __init__(self):
        super(self.__class__, self).__init__()
        self.setWindowTitle("Age in Hours")
        self.setGeometry(200, 200, 350, 150)
#         self.setWindowIcon(QtGui.QIcon("favicon.png"))
        self.initUi()

    def initUi(self):
        self.centralWidget = QtGui.QWidget(self)
        lyt_central = QtGui.QVBoxLayout(self.centralWidget)

        lbl_instructions = QtGui.QLabel("How much time has passed \
since your birth?")

        lyt_year = QtGui.QHBoxLayout()
        lbl_year = QtGui.QLabel("Year:    ")
        self.slr_year = QtGui.QSlider(QtCore.Qt.Horizontal)
        self.slr_year.setMinimum(0)
        self.slr_year.setMaximum(25)
        self.slr_year.setValue(21)
        self.slr_year.setTickPosition(QtGui.QSlider.TicksBelow)
        self.slr_year.setTickInterval(1)
        self.slr_year.valueChanged.connect(self.year_change)
        self.slr_year.valueChanged.connect(self.calculate_hours)
        self.led_year = QtGui.QLineEdit()
        self.led_year.returnPressed.connect(
                lambda: self.slr_year.setValue(int(self.led_year.text())))
        self.led_year.setFixedWidth(55)
        lyt_year.addWidget(lbl_year)
        lyt_year.addWidget(self.slr_year)
        lyt_year.addWidget(self.led_year)

        lyt_month = QtGui.QHBoxLayout()
        lbl_month = QtGui.QLabel("Month: ")
        self.slr_month = QtGui.QSlider(QtCore.Qt.Horizontal)
        self.slr_month.setMinimum(0)
        self.slr_month.setMaximum(12)
        self.slr_month.setValue(8)
        self.slr_month.setTickPosition(QtGui.QSlider.TicksBelow)
        self.slr_month.setTickInterval(1)
        self.slr_month.valueChanged.connect(self.month_change)
        self.slr_month.valueChanged.connect(self.calculate_hours)
        self.led_month = QtGui.QLineEdit()
        self.led_month.returnPressed.connect(
                lambda: self.slr_month.setValue(int(self.led_month.text())))
        self.led_month.setFixedWidth(55)
        lyt_month.addWidget(lbl_month)
        lyt_month.addWidget(self.slr_month)
        lyt_month.addWidget(self.led_month)

        lyt_day = QtGui.QHBoxLayout()
        lbl_day = QtGui.QLabel("Day:     ")  # extra spaces to match alignment
        self.slr_day = QtGui.QSlider(QtCore.Qt.Horizontal)
        self.slr_day.setMinimum(0)
        self.slr_day.setMaximum(31)
        self.slr_day.setValue(7)
        self.slr_day.setTickPosition(QtGui.QSlider.TicksBelow)
        self.slr_day.setTickInterval(1)
        self.slr_day.valueChanged.connect(self.day_change)
        self.slr_day.valueChanged.connect(self.calculate_hours)
        self.led_day = QtGui.QLineEdit()
        self.led_day.returnPressed.connect(
                lambda: self.slr_day.setValue(int(self.led_day.text())))
        self.led_day.setFixedWidth(55)
        lyt_day.addWidget(lbl_day)
        lyt_day.addWidget(self.slr_day)
        lyt_day.addWidget(self.led_day)

        lyt_output = QtGui.QHBoxLayout()
        lbl_output = QtGui.QLabel("Your age in hours is approximately: ")
        self.lbl_output_data = QtGui.QLabel()
        lyt_output.addWidget(lbl_output)
        lyt_output.addWidget(self.lbl_output_data)

        lyt_central.addWidget(lbl_instructions)
        lyt_central.addLayout(lyt_year)
        lyt_central.addLayout(lyt_month)
        lyt_central.addLayout(lyt_day)
        lyt_central.addLayout(lyt_output)
        self.setCentralWidget(self.centralWidget)

    def year_change(self, value):
        self.led_year.setText(str(value))

    def month_change(self, value):
        self.led_month.setText(str(value))

    def day_change(self, value):
        self.led_day.setText(str(value))

    def calculate_hours(self):
        """Get years, months and days and update the age."""
        year = int(self.slr_year.value())
        month = int(self.slr_month.value())
        day = int(self.slr_day.value())

        final_output = (year * 365.25 * 24) + (month * 30 * 24) + (day * 24)

        self.lbl_output_data.setText(str(final_output))


    def keyPressEvent(self, e):
        """Response to keypresses."""
        if e.key() == QtCore.Qt.Key_Escape:
            self.close()

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    w = AgeInHours()
    w.show()
    sys.exit(app.exec_())
\$\endgroup\$
6
\$\begingroup\$

It looks like you're manually trying to calculate the amount of hours since birth, which will be difficult because of leap years and the general difficulty of working with dates. I would recommend using the datetime module instead:

from datetime import datetime
current_time = datetime.now()
# Use the information you collect in your GUI to enter a datetime for birth; call this variable birth_time
time_diff = current_time - birth_time
hours = round(time_diff.total_seconds() / 3600)
\$\endgroup\$
2
  • \$\begingroup\$ That's something new I learnt today. Anything else you would suggest? \$\endgroup\$ – Santosh Kumar Jul 12 '18 at 17:15
  • \$\begingroup\$ When working with dates and times, I follow the advice of Tom Scott in this Computerphile video: youtube.com/watch?v=-5wpm-gesOY. The advice is simple: when working with dates and times, always use your language's built-in libraries. Never try to use your own date/time modules, because you will somehow mess up and/or have a huge headache from working with all the edge cases. \$\endgroup\$ – Joel Jul 13 '18 at 12:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.