Skip to content

Commit cca83b7

Browse files
committed
Introduce DateFormatter and NumberFormatter
Introduce formatters for the typical use cases of formatting numbers and dates. Internally, those formatters use `number_format` and `date_format` respectively. If a date cannot be parsed in runtime, the formatter will return the input unmodified. Similarly, if some input is not numeric, the numeric formatter will return it unchanged.
1 parent 99829b7 commit cca83b7

File tree

7 files changed

+860
-0
lines changed

7 files changed

+860
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
SPDX-FileCopyrightText: (c) Respect Project Contributors
33
SPDX-License-Identifier: ISC
44
SPDX-FileContributor: Henrique Moody <henriquemoody@gmail.com>
5+
SPDX-FileContributor: Alexandre Gomes Gaigalas <alganet@gmail.com>
56
-->
67

78
# Respect\StringFormatter
@@ -38,7 +39,9 @@ echo f::create()
3839

3940
| Formatter | Description |
4041
| ---------------------------------------------------- | --------------------------------------------------- |
42+
| [DateFormatter](docs/DateFormatter.md) | Date and time formatting with flexible parsing |
4143
| [MaskFormatter](docs/MaskFormatter.md) | Range-based string masking with Unicode support |
44+
| [NumberFormatter](docs/NumberFormatter.md) | Number formatting with thousands and decimal separators |
4245
| [PatternFormatter](docs/PatternFormatter.md) | Pattern-based string filtering with placeholders |
4346
| [PlaceholderFormatter](docs/PlaceholderFormatter.md) | Template interpolation with placeholder replacement |
4447

docs/DateFormatter.md

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
<!--
2+
SPDX-FileCopyrightText: (c) Respect Project Contributors
3+
SPDX-License-Identifier: ISC
4+
SPDX-FileContributor: Alexandre Gomes Gaigalas <alganet@gmail.com>
5+
-->
6+
7+
# DateFormatter
8+
9+
The `DateFormatter` parses and reformats date and time strings using flexible input parsing and configurable output formats.
10+
11+
## Usage
12+
13+
### Basic Usage
14+
15+
```php
16+
use Respect\StringFormatter\DateFormatter;
17+
18+
$formatter = new DateFormatter();
19+
20+
echo $formatter->format('2024-01-15 10:30:45');
21+
// Outputs: 2024-01-15 10:30:45
22+
```
23+
24+
### Custom Format
25+
26+
```php
27+
use Respect\StringFormatter\DateFormatter;
28+
29+
$formatter = new DateFormatter('m/d/Y');
30+
31+
echo $formatter->format('2024-01-15');
32+
// Outputs: 01/15/2024
33+
```
34+
35+
### European Format
36+
37+
```php
38+
use Respect\StringFormatter\DateFormatter;
39+
40+
$formatter = new DateFormatter('d.m.Y');
41+
42+
echo $formatter->format('2024-01-15');
43+
// Outputs: 15.01.2024
44+
```
45+
46+
### With Month Names
47+
48+
```php
49+
use Respect\StringFormatter\DateFormatter;
50+
51+
$formatter = new DateFormatter('l, F j, Y');
52+
53+
echo $formatter->format('2024-01-15');
54+
// Outputs: Monday, January 15, 2024
55+
```
56+
57+
### ISO 8601 Format
58+
59+
```php
60+
use Respect\StringFormatter\DateFormatter;
61+
62+
$formatter = new DateFormatter('c');
63+
64+
echo $formatter->format('2024-01-15T10:30:45+00:00');
65+
// Outputs: 2024-01-15T10:30:45+00:00
66+
```
67+
68+
## API
69+
70+
### `DateFormatter::__construct`
71+
72+
- `__construct(string $format = 'Y-m-d H:i:s')`
73+
74+
Creates a new formatter instance with the specified date format.
75+
76+
**Parameters:**
77+
78+
- `$format`: PHP date format string (default: `'Y-m-d H:i:s'`)
79+
80+
### `format`
81+
82+
- `format(string $input): string`
83+
84+
Parses the input date string and formats it according to the formatter's configuration.
85+
86+
If the input cannot be parsed as a date, it is returned unchanged without modification.
87+
88+
**Parameters:**
89+
90+
- `$input`: A date string in any format parseable by `DateTime`
91+
92+
**Returns:** The formatted date string if the input can be parsed; the input unchanged otherwise
93+
94+
## Behavior
95+
96+
### Strict Date Validation
97+
98+
The formatter uses a two-level validation approach:
99+
100+
1. **Exception handling**: Catches `DateMalformedStringException` thrown by invalid format strings
101+
2. **Error checking**: Uses `DateTime::getLastErrors()` to detect parsing errors and warnings
102+
103+
This ensures even dates that appear parseable but have parsing issues are rejected.
104+
105+
### Valid Input
106+
107+
The formatter uses PHP's `DateTime` constructor which supports various date formats including ISO 8601, MySQL format, relative formats (like "now", "tomorrow"), and other flexible formats. Valid input must parse without errors or warnings.
108+
109+
```php
110+
$formatter = new DateFormatter('Y-m-d');
111+
112+
// Valid date input
113+
echo $formatter->format('2024-01-15'); // Outputs: 2024-01-15
114+
echo $formatter->format('2024-01-15 10:30:45'); // Outputs: 2024-01-15
115+
echo $formatter->format('January 15, 2024'); // Outputs: 2024-01-15
116+
```
117+
118+
### Invalid Input
119+
120+
When input cannot be parsed as a date or has parsing errors/warnings, the formatter returns it unchanged:
121+
122+
```php
123+
$formatter = new DateFormatter('Y-m-d');
124+
125+
// Invalid input is returned unchanged
126+
echo $formatter->format('invalid date'); // Outputs: invalid date
127+
echo $formatter->format('this-is-not-a-date'); // Outputs: this-is-not-a-date
128+
echo $formatter->format('N/A'); // Outputs: N/A
129+
```
130+
131+
## Input Formats
132+
133+
The formatter uses PHP's `DateTime` constructor which supports various input formats:
134+
135+
### Standard Date Formats
136+
137+
| Format | Example |
138+
|---------------|-----------------------|
139+
| ISO 8601 | `2024-01-15T10:30:45` |
140+
| MySQL | `2024-01-15 10:30:45` |
141+
| US Format | `01/15/2024` |
142+
| European | `15.01.2024` |
143+
| Unix Timestamp| `@1705331445` |
144+
145+
## Output Format Strings
146+
147+
### Year
148+
149+
| Format | Description | Example |
150+
|--------|--------------------------|---------|
151+
| `Y` | 4-digit year | 2024 |
152+
| `y` | 2-digit year | 24 |
153+
154+
### Month
155+
156+
| Format | Description | Example |
157+
|--------|--------------------------|---------|
158+
| `m` | 2-digit month | 01 |
159+
| `n` | Month without leading 0 | 1 |
160+
| `F` | Full month name | January |
161+
| `M` | 3-letter month | Jan |
162+
163+
### Day
164+
165+
| Format | Description | Example |
166+
|--------|--------------------------|---------|
167+
| `d` | 2-digit day | 15 |
168+
| `j` | Day without leading 0 | 15 |
169+
| `D` | 3-letter weekday | Mon |
170+
| `l` | Full weekday name | Monday |
171+
172+
### Time
173+
174+
| Format | Description | Example |
175+
|--------|--------------------------|---------|
176+
| `H` | 24-hour format (00-23) | 10 |
177+
| `h` | 12-hour format (01-12) | 10 |
178+
| `i` | Minutes (00-59) | 30 |
179+
| `s` | Seconds (00-59) | 45 |
180+
| `A` | AM/PM uppercase | AM |
181+
| `a` | am/pm lowercase | am |
182+
183+
### Other
184+
185+
| Format | Description | Example |
186+
|--------|--------------------------|---------------------------------|
187+
| `c` | ISO 8601 | 2024-01-15T10:30:45+00:00 |
188+
| `r` | RFC 2822 | Mon, 15 Jan 2024 10:30:45 +0000 |
189+
| `U` | Unix timestamp | 1705331445 |
190+
| `z` | Day of year (0-365) | 014 |
191+
| `W` | Week number (ISO-8601) | 02 |
192+
193+
## Examples
194+
195+
### Common Formats
196+
197+
| Description | Format | Input | Output |
198+
|-------------------|------------------|-------------------------|-----------------------------------|
199+
| US Date | `m/d/Y` | `2024-01-15` | `01/15/2024` |
200+
| European Date | `d.m.Y` | `2024-01-15` | `15.01.2024` |
201+
| Time Only | `H:i:s` | `2024-01-15 10:30:45` | `10:30:45` |
202+
| Long Format | `l, F j, Y` | `2024-01-15` | `Monday, January 15, 2024` |
203+
| Short Format | `M d, Y` | `2024-01-15` | `Jan 15, 2024` |
204+
| ISO 8601 | `c` | `2024-01-15T10:30:45` | `2024-01-15T10:30:45+00:00` |
205+
| RFC 2822 | `r` | `2024-01-15 10:30:45` | `Mon, 15 Jan 2024 10:30:45 +0000` |
206+
207+
### Parsing Flexibility
208+
209+
The formatter intelligently parses various input formats:
210+
211+
```php
212+
$formatter = new DateFormatter('Y-m-d');
213+
214+
// All produce the same output: 2024-01-15
215+
echo $formatter->format('2024-01-15'); // ISO format
216+
echo $formatter->format('01/15/2024'); // US format
217+
echo $formatter->format('15.01.2024'); // European format
218+
echo $formatter->format('January 15, 2024'); // Long format
219+
```
220+
221+
### Relative Date Processing
222+
223+
```php
224+
$formatter = new DateFormatter('l, F j, Y');
225+
226+
echo $formatter->format('now'); // Today's date
227+
echo $formatter->format('tomorrow'); // Tomorrow's date
228+
echo $formatter->format('yesterday'); // Yesterday's date
229+
```

0 commit comments

Comments
 (0)