RepoPilotOpen in app →

square/android-times-square

Standalone Android widget for picking a single date from a calendar view.

Healthy

Healthy across all four use cases

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 28+ active contributors
  • Distributed ownership (top contributor 42% of recent commits)
  • Apache-2.0 licensed
Show all 6 evidence items →
  • CI configured
  • Tests present
  • Stale — last commit 3y ago

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/square/android-times-square)](https://repopilot.app/r/square/android-times-square)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/square/android-times-square on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: square/android-times-square

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/square/android-times-square shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across all four use cases

  • 28+ active contributors
  • Distributed ownership (top contributor 42% of recent commits)
  • Apache-2.0 licensed
  • CI configured
  • Tests present
  • ⚠ Stale — last commit 3y ago

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live square/android-times-square repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/square/android-times-square.

What it runs against: a local clone of square/android-times-square — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in square/android-times-square | Confirms the artifact applies here, not a fork | | 2 | License is still Apache-2.0 | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 1107 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>square/android-times-square</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of square/android-times-square. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/square/android-times-square.git
#   cd android-times-square
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of square/android-times-square and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "square/android-times-square(\\.git)?\\b" \\
  && ok "origin remote is square/android-times-square" \\
  || miss "origin remote is not square/android-times-square (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
  && ok "license is Apache-2.0" \\
  || miss "license drift — was Apache-2.0 at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "library/src/main/java/com/squareup/timessquare/CalendarPickerView.java" \\
  && ok "library/src/main/java/com/squareup/timessquare/CalendarPickerView.java" \\
  || miss "missing critical file: library/src/main/java/com/squareup/timessquare/CalendarPickerView.java"
test -f "library/src/main/java/com/squareup/timessquare/MonthDescriptor.java" \\
  && ok "library/src/main/java/com/squareup/timessquare/MonthDescriptor.java" \\
  || miss "missing critical file: library/src/main/java/com/squareup/timessquare/MonthDescriptor.java"
test -f "library/src/main/java/com/squareup/timessquare/CalendarCellView.java" \\
  && ok "library/src/main/java/com/squareup/timessquare/CalendarCellView.java" \\
  || miss "missing critical file: library/src/main/java/com/squareup/timessquare/CalendarCellView.java"
test -f "library/src/main/java/com/squareup/timessquare/CalendarGridView.java" \\
  && ok "library/src/main/java/com/squareup/timessquare/CalendarGridView.java" \\
  || miss "missing critical file: library/src/main/java/com/squareup/timessquare/CalendarGridView.java"
test -f "library/src/main/java/com/squareup/timessquare/DayViewAdapter.java" \\
  && ok "library/src/main/java/com/squareup/timessquare/DayViewAdapter.java" \\
  || miss "missing critical file: library/src/main/java/com/squareup/timessquare/DayViewAdapter.java"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 1107 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~1077d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/square/android-times-square"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

TimesSquare is a lightweight, standalone Android widget library that renders an interactive calendar grid for single-date or range-date selection. It provides CalendarPickerView, a customizable month/week view component that handles date initialization, cell rendering, and multi-selection modes (single, range, multiple) without dependencies on heavy date libraries. Monolithic single-library structure: library/src/main/java/com/squareup/timessquare/ contains all core logic as a flat package of 13 Java classes. CalendarPickerView.java is the main public API, delegating to CalendarGridView, MonthView, CalendarRowView, and CalendarCellView for rendering. Layout XMLs in library/src/main/res/layout/ (month.xml, week.xml) define the view hierarchy; colors and drawables define styling.

👥Who it's for

Android application developers who need to embed a native date picker widget in their apps (activities, fragments, or dialogs) without using system dialogs or heavy third-party date libraries. Particularly useful for developers targeting Android API 14+ who want fine-grained UI control over calendar presentation.

🌱Maturity & risk

Production-ready and actively maintained by Square. The library has been in use since 2012 with stable releases (currently at 1.6.5), includes CI via GitHub Actions (see .github/workflows/android.yml), uses Gradle/Maven for dependency management, and targets modern Android (minSdk 14, compileSdk 31). However, commit recency and issue backlog are not visible in provided data; check the GitHub repo directly for latest activity status.

Low-risk library with minimal external dependencies (only test deps like Robolectric and JUnit visible). The single-purpose nature (calendar widget only) reduces breaking-change surface. Main risks: API 14 baseline is 11+ years old, and if Square has reduced maintenance focus, critical bugs may go unaddressed. No major version bumps in recent data suggest API stability but potentially stagnant development.

Active areas of work

No active development details visible in provided file list. Check GitHub Issues/PRs and CHANGELOG.md for recent activity. The presence of RELEASING.md and .buildscript/deploy_snapshot.sh indicates a mature release pipeline, but specific recent work is not evident from the structural data alone.

🚀Get running

git clone https://github.com/square/android-times-square.git
cd android-times-square
./gradlew build
./gradlew :library:assembleDebug

Then import the library/ submodule into your Android project or publish to local Maven via ./gradlew :library:publishToMavenLocal.

Daily commands: No standalone server/app—TimesSquare is a library. To test in a demo app: Create a minimal Activity layout with <com.squareup.timessquare.CalendarPickerView>, initialize it in onCreate() with calendar.init(startDate, endDate).withSelectedDate(today), and call calendar.getSelectedDate() or getSelectedDates() for user selections. Run via Android Studio's emulator or ./gradlew installDebug.

🗺️Map of the codebase

  • library/src/main/java/com/squareup/timessquare/CalendarPickerView.java — Core widget entry point—orchestrates calendar initialization, date selection, and view setup; every contributor must understand its init() and withSelectedDate() API.
  • library/src/main/java/com/squareup/timessquare/MonthDescriptor.java — Data model for a calendar month; essential for understanding how months are structured and populated with day cells.
  • library/src/main/java/com/squareup/timessquare/CalendarCellView.java — Individual day cell renderer; defines visual state (selected, disabled, today) and is the unit of date interaction.
  • library/src/main/java/com/squareup/timessquare/CalendarGridView.java — GridView adapter and layout controller for the calendar's month grid; bridges data model to cell views.
  • library/src/main/java/com/squareup/timessquare/DayViewAdapter.java — Interface for custom day cell rendering; critical extension point for styling and decoration.
  • library/build.gradle — Library-specific build configuration, dependencies, and artifact publishing settings.

🛠️How to make changes

Add Custom Day Cell Styling

  1. Create a class implementing DayViewAdapter interface in library/src/main/java/com/squareup/timessquare/ (library/src/main/java/com/squareup/timessquare/DayViewAdapter.java)
  2. Implement getView() to return a custom View with your styling (see sample implementation) (sample/src/main/java/com/squareup/timessquare/sample/SampleDayViewAdapter.java)
  3. In CalendarPickerView initialization, call .withDayViewAdapter(yourAdapter) before showing calendar (library/src/main/java/com/squareup/timessquare/CalendarPickerView.java)
  4. Test visuals in sample app by instantiating your adapter in SampleTimesSquareActivity (sample/src/main/java/com/squareup/timessquare/sample/SampleTimesSquareActivity.java)

Add Calendar Cell Decoration (Highlighting Events)

  1. Create a class implementing CalendarCellDecorator interface (library/src/main/java/com/squareup/timessquare/CalendarCellDecorator.java)
  2. Implement decorate() to modify CalendarCellView state based on MonthCellDescriptor date (sample/src/main/java/com/squareup/timessquare/sample/SampleDecorator.java)
  3. Register decorator via calendar.withDecorators(yourDecorator) after init() (library/src/main/java/com/squareup/timessquare/CalendarPickerView.java)

Customize Calendar Colors and Text via Resources

  1. Override color values in your app's values/colors.xml (calendar_text_color, calendar_bg_color, etc.) (library/src/main/res/values/colors.xml)
  2. Override drawable selectors in your app's drawables/ directory matching library names (library/src/main/res/drawable/calendar_bg_selector.xml)
  3. Optionally override text selector colors (library/src/main/res/color/calendar_text_selector.xml)
  4. Reference custom selectors in CalendarCellView initialization (DefaultDayViewAdapter uses them) (library/src/main/java/com/squareup/timessquare/DefaultDayViewAdapter.java)

Add Support for a New Language

  1. Create a new locale directory under library/src/main/res/ (e.g., values-zh for Chinese) (library/src/main/res/values/strings.xml)
  2. Copy strings.xml into your locale directory and translate month/day names (library/src/main/res/values-de/strings.xml)
  3. Android's localization system automatically uses the translated strings at runtime based on device locale

🔧Why these technologies

  • Android GridView — Efficient scrolling container for large month datasets; automatically recycles row views to minimize memory.
  • Calendar.getInstance() / Java Date — Legacy but reliable date handling for consistent cross-version behavior before Java 8 Time API adoption.
  • Custom ViewGroup subclasses (CalendarRowView, MonthView) — Fine-grained layout control for grid alignment and cell spacing; simpler than complex adapter layouts.
  • Android Resource selectors (drawable, color XML) — Declarative state-based styling (selected, disabled, today) without code; easy customization via override.
  • Interface-based decoration (DayViewAdapter, CalendarCellDecorator) — Pluggable rendering and post-processing without modifying core;

🪤Traps & gotchas

No obvious hidden traps in the provided data. However: (1) minSdkVersion = 14 (API 14, Android 4.0) is very old—verify your app's minSdk compatibility. (2) Java 11 required for compilation (sourceCompatibilityVersion = JavaVersion.VERSION_11)—ensure your build environment has Java 11+. (3) Robolectric 4.7.3 may have issues with newer Android Gradle Plugin versions; check test compatibility if upgrading. (4) IndexedLinkedHashMap.java is a custom collection—understand its behavior before relying on iteration order.

🏗️Architecture

💡Concepts to learn

  • Custom ViewGroup Rendering — TimesSquare builds the calendar by extending ViewGroup and managing child Views (MonthView, CalendarRowView, CalendarCellView) programmatically; understanding View measurement/layout is essential to debug rendering issues.
  • Adapter Pattern (CalendarCellDecorator) — The decorator pattern allows external code to customize cell appearance without modifying core CalendarPickerView—critical for extending functionality.
  • Builder Pattern (Fluent Configuration) — CalendarPickerView.init().inMode().withSelectedDate() uses method chaining—understanding this pattern helps add new configuration options.
  • State Machine (RangeState enum) — Range selection mode uses RangeState to track whether a cell is before-range, in-range, or after-range; essential for understanding multi-date selection logic.
  • Android Resource Selectors (drawable/color selectors) — Calendar styling uses drawable and color selectors (calendar_bg_selector.xml, calendar_text_selector.xml) to respond to cell state changes (selected, pressed, disabled).
  • Calendar Arithmetic (Java Calendar API) — MonthDescriptor and MonthCellDescriptor use Java's Calendar class to compute month layouts, day-of-week positions, and leap year handling.
  • Linked Hash Map (IndexedLinkedHashMap) — Custom map implementation preserves insertion order and provides indexed access; used internally for efficient date storage and lookup.
  • prolific-dev/monthly-calendar — Alternative calendar widget library for Android with similar date-picking functionality but with range and event marker support.
  • wduleba/MaterialDateTimePicker — Material Design date/time picker for Android using a similar custom View approach, offers UI patterns TimesSquare could adopt.
  • roomorama/Caldroid — Fragment-based calendar library with grid view; predecessor pattern in the Android calendar widget ecosystem.
  • square/okhttp — Fellow Square open-source library; same organization's infrastructure for Gradle builds, CI/CD, and release pipelines.
  • square/android-times-square-test — If it exists, would contain integration tests and sample app for this library (verify on GitHub).

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add unit tests for CalendarPickerView initialization and date selection logic

The repo has robolectric (4.7.3) and junit (4.13.2) as test dependencies but no visible test files in the structure. CalendarPickerView is the core widget and lacks unit test coverage for initialization with date ranges, date selection callbacks, and state management. This is critical for a calendar widget where date handling bugs are high-impact.

  • [ ] Create library/src/test/java/com/squareup/timessquare/ directory structure
  • [ ] Add CalendarPickerViewTest.java testing initialization with Calendar range, selected dates, and invalid date handling
  • [ ] Add MonthDescriptor and MonthCellDescriptor unit tests for date calculations
  • [ ] Add tests for RangeState.java to verify state transitions (selectable, selected, highlighted)
  • [ ] Run tests with Robolectric to verify Android view behavior

Upgrade targetSdkVersion from 30 to 33+ and add Android 12/13 compatibility tests

The repo targets SDK 30 (Android 11) which is 2+ years old. Modern Google Play requires targeting SDK 34+. The build.gradle shows compileSdkVersion = 31, indicating the project hasn't kept pace with platform evolution. This PR would add CI testing for newer Android versions and ensure the widget works with current restrictions (restricted broadcasts, pending intents, etc.).

  • [ ] Update compileSdkVersion to 34 and targetSdkVersion to 34 in gradle.properties and library/build.gradle
  • [ ] Review AndroidManifest.xml for any deprecated permissions or broadcast receivers that need updating
  • [ ] Add a new GitHub Actions workflow job in .github/workflows/android.yml to test against Android API 33 and 34 emulators
  • [ ] Test CalendarCellView.java and CalendarGridView.java rendering on modern SDK versions
  • [ ] Update CHANGELOG.md with SDK upgrade notes

Add comprehensive integration tests using Espresso for CalendarPickerView user interactions

While robolectric is present for unit tests, there are no visible integration tests for user interactions (clicking dates, swiping months, selecting ranges if supported). Espresso tests would validate the actual UI behavior of DayViewAdapter, CalendarRowView, and month navigation—critical for a user-facing widget.

  • [ ] Create library/src/androidTest/ directory with Espresso test classes
  • [ ] Add CalendarPickerViewInteractionTest.java testing: tapping individual dates, verifying selection state updates, month navigation
  • [ ] Add tests for edge cases: clicking disabled dates, selecting date ranges, rapid successive clicks
  • [ ] Update library/build.gradle with androidTestImplementation dependencies (androidx.test.espresso:espresso-core, androidx.test.ext:junit)
  • [ ] Add Espresso test job to .github/workflows/android.yml using connected device or emulator

🌿Good first issues

  • Add unit tests for CalendarPickerView.init() method with various date ranges and edge cases (leap years, month boundaries). Currently only Robolectric/unit test framework is available; test files are not visible in the file list.
  • Implement localization for day-of-week headers beyond the current strings-.xml translations (German, Esperanto, Spanish, French visible in res/values-/). Missing translation files for other languages could be added with contributor guidance.
  • Create a sample Android app in an examples/ directory demonstrating all three selection modes (SINGLE, RANGE, MULTIPLE) with code comments. No example app is currently visible in the file list.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 36e247f — Turkish translation of invalid date string (#515) (Suleyman BİLGİN)
  • a1a8f2b — Prepare next development version (Eric Denman)
  • d3f830d — Prepare for release 1.7.11 (Eric Denman)
  • 4a6bf8d — Add new maven release plugin, add RELEASING.md instructions (#514) (edenman)
  • c6c67ad — Fix - Support Theme Attributes For tsquare_dayTextColor (fixes #509) (#510) (quentin41500)
  • f2d4966 — Lots of updates to enable building with Github Actions (#511) (edenman)
  • 7f2f3ca — Update to modern tooling (edenman)
  • 83b08e7 — Remove gradle/wrapper/gradle-wrapper. which seems to be there by accident. (#470) (tobiasschuerg)
  • 0e37b74 — Add changelog for 1.7.10, bump to 1.7.11-SNAPSHOT (edenman)
  • 4b9c01f — Ukrainian translation of invalid_date string (#450) (ViTVetal)

🔒Security observations

The codebase has a moderate security posture with several concerns related to outdated dependencies and configurations. The primary risks stem from: (1) use of alpha/pre-release versions for critical build tools and Android framework libraries, (2) significantly outdated target SDK version that doesn't meet modern Android standards, (3) reliance on JitPack repository which introduces supply chain risk, and (4) generally outdated dependency versions across the board. The widget itself (a calendar picker) has minimal attack surface and no apparent injection vulnerabilities based on its simple functionality. However, the dependency management practices should be improved immediately to ensure security and compliance with Android ecosystem requirements.

  • High · Outdated Gradle Plugin Version — build.gradle (classpath 'com.android.tools.build:gradle:7.3.0-alpha07'). The project uses Gradle plugin version 7.3.0-alpha07, which is an alpha release. Alpha versions are not recommended for production use as they may contain unpatched security vulnerabilities and lack stability guarantees. Fix: Update to the latest stable version of the Android Gradle plugin (currently 8.x or higher) to ensure security patches and stability.
  • High · Outdated AndroidX Core Dependency — build.gradle (androidXCore: 'androidx.core:core:1.9.0-alpha01'). The project uses AndroidX Core 1.9.0-alpha01, an alpha version that may contain unpatched security vulnerabilities and lacks production stability guarantees. Fix: Update to the latest stable version of androidx.core (currently 1.10.x or higher).
  • Medium · Outdated Robolectric Dependency — build.gradle (robolectric: 'org.robolectric:robolectric:4.7.3'). The project uses Robolectric 4.7.3, which is significantly outdated. Current versions are 4.10+. This may expose test environments to known vulnerabilities. Fix: Update Robolectric to the latest stable version (4.11.x or higher).
  • Medium · Low Target SDK Version — build.gradle (targetSdkVersion = 30). The project targets SDK version 30, which is outdated. Google Play Store now requires targeting API level 34 (Android 14) for new apps and higher for updates. This may prevent distribution on modern Android devices and miss important security patches. Fix: Update targetSdkVersion to at least 34 to comply with Google Play Store requirements and ensure modern security features are utilized.
  • Medium · Outdated Gradle Maven Publish Plugin — build.gradle (classpath 'com.vanniktech:gradle-maven-publish-plugin:0.18.0'). The gradle-maven-publish-plugin version 0.18.0 is outdated. Current versions are 0.25.x or higher. This may contain unpatched vulnerabilities in the build and publishing pipeline. Fix: Update to the latest stable version of gradle-maven-publish-plugin (0.25.x or higher).
  • Medium · JitPack Maven Repository — build.gradle (maven { url 'https://jitpack.io' }). The project includes JitPack (https://jitpack.io) as a Maven repository. JitPack builds dependencies from public Git repositories on-demand, which may introduce risks if used for critical dependencies. There's potential for supply chain attacks if dependencies are compromised. Fix: Evaluate whether JitPack dependencies are necessary. Prefer official Maven Central or Google Maven repositories. If JitPack is required, pin specific versions and monitor for suspicious changes.
  • Low · Deprecated IntelliJ Annotations Library — build.gradle (intellijannotations: 'org.jetbrains:annotations:16.0.2'). The project uses org.jetbrains:annotations:16.0.2, an outdated version from 2018. Newer versions provide improved compatibility and fixes. Fix: Update to the latest stable version of jetbrains-annotations (23.x or higher).

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · square/android-times-square — RepoPilot