Project

General

Profile

Feature #20298

Updated by ioquatix (Samuel Williams) 2 months ago

Many Ruby primitive types have constructors, e.g. `Integer(...)`, `String(...)`, `Float(...)`, etc. These usually convert from some subset of types, e.g. `Float(1) -> 1.0` will convert an Integer to a Float, and `Float("1") -> 1.0` will parse a String to a Float, and similar for other type casts/constructors. 

 I'd like to propose we introduce something similar for `Time` (and possibly this extends to `Date`/`DateTime` in a follow up proposal). 

 Suggested implementation could look something like this: 

 ```ruby 
 def Time(value) 
   case value 
   when Time 
     value 
   when Integer 
     Time.at(value) 
   when String # The format is assumed to be the result of `Time#to_s`. 
     Time.new(value) Time.parse(value) 
   else 
     value.to_time 
   end 
 end 
 ``` 

 Alternatively, we might like to be a little more specific with the `else` clause/error handling. 

 ## Background 

 In a project, I need to support multiple serialization formats/coders, including MessagePack, Marshal and JSON. 

 While Marshal and MessagePack are capable of serializing `Time` instances, `JSON` is not. 

 The code looks a bit like this: 

 ``` 
 data = fetch_job_data 
 job = @coder.load(data) 
 scheduled_at = Time(job[:scheduled_at]) # Hypothetical type-cast as outlined above 
 ``` 

 ## Additional Observations 

 While some primitive data types accept themselves as arguments and construct by copy, e.g. `Array.new(Array.new)`, others do not, e.g. `Hash` and `Time`. Perhaps `Time.new(Time.new)` should behave similarly to `Array.new(Array.new)` - the outer instance is a copy of the inner. 

Back