At work, I’ve been heading up an Asset Management project. Inventorying everything we have, adding it to a system, and then figuring out replacement cycles, amortization, etc. Part of this has been figuring out purchase dates for things like Macs, without asking our overloaded accounting office for invoices for a couple hundred machines.
Some investigation led me to two websites, one covering the new serial numbers, and the other covering older serial numbers. Basically, they used to be very readable with numbers representing their actual numbers. Then Apple switched to using Base-27 to represent year (first or second half), and then week was similar (using a limited set of letters and numbers).
Using that information, I’ve created the following script (yes, it’s pretty ugly PHP) that should decode both old 11 digit serials, and new 12 digit ones. Because of my use case, it adds some time to the manufacturing date to come up with a reasonable “purchase date” that I then use ((in my case, it just figures the purchase date was the start of the term following manufacture)). Feel free to use, modify, etc. I just built this because the sites that actually give manufacture date usually have limits on the number of queries per hour/day etc.
Thanks!
‘2005-1’,
‘1’ => ‘2005-2’,
‘2’ => ‘2006-1’,
‘3’ => ‘2006-2’,
‘4’ => ‘2007-1’,
‘5’ => ‘2007-2’,
‘7’ => ‘2008-2’,
‘8’ => ‘2009-1’,
‘9’ => ‘2009-2’,
‘C’ => ‘2010-1’,
‘D’ => ‘2010-2’,
‘F’ => ‘2011-1’,
‘G’ => ‘2011-2’,
‘H’ => ‘2012-1’,
‘J’ => ‘2012-2’,
‘K’ => ‘2013-1’,
‘L’ => ‘2013-2’,
‘M’ => ‘2014-1’,
‘N’ => ‘2014-2’,
‘P’ => ‘2015-1’,
‘Q’ => ‘2015-2’,
‘R’ => ‘2016-1’,
‘S’ => ‘2016-2’,
‘T’ => ‘2017-1’,
‘V’ => ‘2017-2’,
‘W’ => ‘2018-1’,
‘X’ => ‘2018-2’,
‘Y’ => ‘2019-1’,
‘Z’ => ‘2019-2’
);
//Years for 11 digit serial. Yes, it ignores the year 2000 and before.
$years11 = array(
‘0’ => ‘2010’,
‘1’ => ‘2001’,
‘2’ => ‘2002’,
‘3’ => ‘2003’,
‘4’ => ‘2004’,
‘5’ => ‘2005’,
‘6’ => ‘2006’,
‘7’ => ‘2007’,
‘8’ => ‘2008’,
‘9’ => ‘2009’,
);
//Week is the next digit following year, specifying weeks 1 through 26.
//Weeks 27 through 52 are designated by the “half” of the year specified above.
$weeks = array(
‘1’ => ‘1’,
‘2’ => ‘2’,
‘3’ => ‘3’,
‘4’ => ‘4’,
‘5’ => ‘5’,
‘6’ => ‘6’,
‘7’ => ‘7’,
‘8’ => ‘8’,
‘9’ => ‘9’,
‘C’ => ’10’,
‘D’ => ’11’,
‘F’ => ’12’,
‘G’ => ’13’,
‘H’ => ’14’,
‘J’ => ’15’,
‘K’ => ’16’,
‘L’ => ’17’,
‘M’ => ’18’,
‘N’ => ’19’,
‘P’ => ’20’,
‘Q’ => ’21’,
‘R’ => ’22’,
‘T’ => ’23’,
‘V’ => ’24’,
‘W’ => ’25’,
‘X’ => ’26’
);
$monthsdays = array(
4 => ’10/01′,
1 => ’01/05′,
2 => ’04/01′,
3 => ’06/20′,
);
$serial = $_GET[‘s’];
$serial = trim(preg_replace(‘/\s+/’, ”, $serial));
$serial_length = strlen($serial);
$output = $_GET[‘o’];
$output = trim(preg_replace(‘/\s+/’, ”, $output));
if ($serial_length == 11) {
//echo “Computer Pre-2012
“;
$year = substr($serial, 2, 1);
$week = substr($serial, 3, 2);
$purchase_year = $years11[$year];
$purchase_week = $week;
} elseif ($serial_length == 12) {
//echo “Computer Post-2012
“;
$year = substr($serial, 3, 1);
$week = substr($serial, 4, 1);
$purchase_year = $years[$year];
$purchase_week = $weeks[$week];
} else {
die(“Nothing to do!”);
}
if(substr($purchase_year, -2,2) == ‘-2′) {
$purchase_week = $purchase_week + 26;
}
$purchase_year = substr($purchase_year, 0, 4);
if ($purchase_week > 36) {
$purchase_term = 1;
$purchase_year++;
} else {
$purchase_term = ceil($purchase_week/12);
}
$purchase_date = $monthsdays[$purchase_term] . “/” . $purchase_year;
if ($output==’csv’) {
echo $serial . ‘,’ . $purchase_date . “\n”;
} elseif ($output==’date’) {
echo $purchase_date . “\n”;
} else {
echo “Manufacture Year: ” . $years[$year] . ” Manufacture Week: ” . $weeks[$week] . “
“;
echo “Year: ” . $purchase_year . ” Term: ” . $purchase_term . ” Purchase Date: ” . $purchase_date;
}
?>