Concepts / Date and Time Formatting with the time Module

Date and Time Formatting with the time Module

A backup program automates file archiving by using Python to construct and execute a zip command with a timestamped filename.

  • Programming

Why Timestamped Backups Matter

Manually backing up files is tedious and error-prone. You might forget a directory, overwrite an earlier backup, or use an inconsistent filename. A Python backup program automates the process by selecting source directories, creating an archive name based on the current date and time, and executing the backup command.

The central idea is to turn the current date and time into a predictable filename, then place that filename into a zip command executed by the operating system.

What do you think happens?

What should happen when the backup program runs?

  • It only prints a filename and does not create an archive
  • It prints the command, executes it, and reports success or failure
  • It always reports success without checking the command
  • It creates an archive with the same name every time
Reveal answer

Answer: It prints the command, executes it, and reports success or failure.

The program constructs a zip command, displays the command it is about to execute, passes it to os.system(), and checks the returned value. A return value of 0 indicates success; a non-zero value indicates failure.

From Clock to Archive Name

The time.strftime() function converts the current date and time into a formatted string. The format string %Y%m%d%H%M%S contains codes for the year, month, day, hour, minute, and second. When those codes are replaced with the current values, the result can be used as part of the archive filename.

CodeMeaning
%YYear
%mMonth
%dDay
%HHour
%MMinute
%SSecond

Format codes used to build the timestamp string described in the source.

python
Output
A possible output is a timestamp such as 20240115143022. The exact value depends on when the program runs.
formatproduceembedCurrent date andtimetime.strftime()%Y%m%d%H%M%S20240115143022formatted timestampbackup/20240115143022.ziparchive filename
How does the current date and time become a formatted timestamp embedded in the zip filename?

Portable Backup Paths

A path combines a directory with a filename. The directory separator is not written the same way on every operating system: Windows uses a backslash, while macOS and Linux use a forward slash. Python provides os.sep as the separator appropriate for the operating system where the program is running.

python

The construction pattern is the same on every supported operating system: target directory, os.sep, timestamp, and the .zip extension. The visible separator changes with the operating system, but the backup program keeps the same overall behavior.

construct pathconstruct pathconstruct pathWindowsbackup\20240115143022.zipTimestamped ziparchivesame backup behaviormacOSbackup/20240115143022.zipLinuxbackup/20240115143022.zip
How does os.sep change the constructed path on Windows, macOS, and Linux while preserving the same backup behavior?

Constructing the Zip Command

The program builds the zip command as a string. It combines the zip utility, the recursive option, the target archive filename, and the source directories. The -r option tells zip to work recursively through subdirectories.

python

Joining Source Directories

Suppose source contains two entries: /home/user/docs and /home/user/photos. What string does ' '.join(source) create?

Start with the list: The list contains the two source directory paths as separate items.

Join with a space: The join() method places one space between the list items and produces one command-ready string.

Insert into the command: The resulting string is used as the source portion of the zip command.

'/home/user/docs /home/user/photos'

pass command stringexecuteruncreatePython programbuild commandos.system()execute command stringOperating systemshellreceive commandzip-r archive sourcesTimestamped archive.zip file
How does control and data move from the Python backup program through os.system() to the shell, zip command, and final archive?

Checking the Command Result

os.system() executes the command as if it had been typed into a terminal or command prompt. After the command finishes, os.system() returns a value. A return value of 0 means the command succeeded. A non-zero value means it failed. The program uses this result to choose a success or failure message.

python
finish0non-zeroos.system(command)run shell commandReturn value0 or non-zeroBackup succeededBackup failed
What happens after the shell command finishes, and how does its return value indicate whether the backup command succeeded or failed?

Complete Backup Flow

The following is a generated implementation assembled from the source-described steps. It selects source directories, formats a timestamp, constructs the target path with os.sep, joins the source list, builds the zip command, executes it, and checks the return value.

import os import time source = ['docs', 'photos'] target_dir = 'backup' timestamp = time.strftime('%Y%m%d%H%M%S') target = target_dir + os.sep + timestamp + '.zip' source_list = ' '.join(source) command = 'zip -r {0} {1}'.format(target, source_list) print(command) result = os.system(command) if result == 0: print('Backup succeeded') else: print('Backup failed')

Tracing Concrete Values

Trace the program on a Linux system when target_dir is /home/user/backups, source contains /home/user/docs and /home/user/photos, and the formatted timestamp is 20240115143022.

Format the timestamp: time.strftime() produces 20240115143022.

Construct the target: Linux uses a forward slash, so the target becomes /home/user/backups/20240115143022.zip.

Join the sources: The source list becomes /home/user/docs /home/user/photos.

Build the command: The command becomes zip -r /home/user/backups/20240115143022.zip /home/user/docs /home/user/photos.

Execute and inspect: os.system() executes the command. If it returns 0, the program prints the success message; otherwise it prints the failure message.

The program sends a timestamped recursive zip command to the shell and reports the result returned by os.system().

Mistakes to Avoid

  • Hardcoding one directory separator

    The source emphasizes that Windows uses a backslash while macOS and Linux use a forward slash.

    Fix: Use target_dir + os.sep + timestamp + '.zip'.

  • Using a fixed archive name

    A fixed name can overwrite an earlier backup instead of preserving timestamped archives.

    Fix: Include the string returned by time.strftime() in the filename.

  • Passing the source list directly into the command

    The source list needs to become a space-separated string for the command.

    Fix: Create source_list with ' '.join(source), then insert source_list into the command.

  • Assuming the command succeeded

    The program should use the return value from os.system() to distinguish success from failure.

    Fix: Store the return value and compare it with 0.

  • Running without customizing paths

    The source instructs you to customize source and target_dir for your own system.

    Fix: Choose source directories and a target directory that exist on the system where the program will run.

Practice the Trace

MEDIUM

Assume timestamp is 20251231115959, target_dir is archive, and source is ['work', 'notes']. Write the target path, the joined source string, and the complete zip command. Then state which message the program prints when os.system() returns 0.

Hints
  • Build the target from target_dir, os.sep, timestamp, and .zip.
  • Use a single space between the two source entries.
  • The command begins with zip -r.
  • A return value of 0 selects the success branch.

What do you think happens?

If the command returns a non-zero value, which branch should run?

  • The success branch
  • The failure branch
  • Both branches
  • Neither branch
Reveal answer

Answer: The failure branch.

The program treats 0 as success and any non-zero return value as failure.

Practical Design Lessons

This backup program separates responsibilities. Python handles file selection, timestamped naming, path construction, command construction, and result checking. The zip utility handles the actual recursive compression. This division lets the program use an established operating-system tool rather than implementing compression itself.

A useful automation script does more than start an operation. It prepares clear inputs, uses portable system details, executes the operation, and verifies the result.

Key Takeaways

  • time.strftime('%Y%m%d%H%M%S') converts the current date and time into a timestamp suitable for an archive filename.
  • os.sep supplies the operating system's directory separator instead of forcing one separator into the program.
  • The zip command is built from the recursive option, target archive path, and a space-separated source list.
  • os.system() passes the command to the shell and returns 0 for success or a non-zero value for failure.
  • A complete backup flow constructs the archive name, builds the command, executes it, and checks the result.