Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

Zend Framework: Zend_Measure Component Proposal

Proposed Component Name Zend_Measure
Developer Notes http://framework.zend.com/wiki/display/ZFDEV/Zend_Measure
Proposers Thomas Weidner
Gavin (Zend-liaison)
Revision 4.0 - 25 Jan 2007: API rework, simpler useage
3.1 - 23 July 2006: Corrections based on actual work
3.0 - 18 July 2006: Class redesign based on actual work and comments from Zend
2.0 - 26 June 2006: Complete redesign of class skeleton, added new functions
1.1 - 20 June 2006: Changed class to be static
1.0 - 19 June 2006: Initial release extracted from Zend_Locale Proposal V1.0. (wiki revision: 29)

Table of Contents

1. Overview

Zend_Measure is a locale aware Class which can convert measurement units.
Hint: The name Zend_Measure was taken because Zend_Convert implements to convert between different file-types (Text->Excel, Windows->Unix,...) and not measurement units.

2. References

3. Component Requirements, Constraints, and Acceptance Criteria

  • Lightweight and fast implementation
  • Simple use for ZF-user
  • Handling of different input formats

4. Dependencies on Other Framework Components

5. Theory of Operation

Zend_Measure can convert measurement units between different locales. The Conversion can be done for

  • Length
  • Weight
  • Temperature
  • Area
  • Power
  • Energy
  • and much more...

6. Milestones / Tasks

zone: Missing {zone-data:milestones}

7. Class Index

  • Zend_Measure_Exception
  • Zend_Measure

8. Use Cases

Get output of Kelvin in actual locale

Get formatted output in different locale

Different Input Types which would be recognized

Convert Fahrenheit to Celsius

Convert Kilo to Tonne with other locale

Maths with different units

9. Class Skeletons

]]></ac:plain-text-body></ac:macro>

]]></ac:plain-text-body></ac:macro>

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Jun 20, 2006

    <p>This seems like it would be better implemented at as a library of helper function rather than one big class – especially given that the locale is passed to each method. If it was a library of functions it would be infinitely extensible without needing to include the whole giant class. </p>

    1. Jun 20, 2006

      <p>The locale is not passed explicit.<br />
      When no locale is defined, the standard locale will be taken.</p>

      <p>BUT you can define that the returned result is displayed in a different locale.<br />
      So all locale-parameters are optional as you will see at the first usecase.</p>

      <p>How would the "library of helper functions" look like and be implemented in your thought ?</p>

      <p>Btw: This class is extensible, as its complete PUBLIC.<br />
      Btw2: There are only 11 functions so I don't think thas this is a BIG CLASS.</p>

      1. Jun 20, 2006

        <p>It seems like the methods would be better implemented as static methods, since they wouldn't vary between instances of the original class (though would if the class was extended, in which case it would have a different name anyway and it wouldn't matter if they were static). Beyond that, I think the class is well-designed. I would suggest adding a method to set an override for the default locale and have all methods use that locale unless a different one is specified in calls to them.</p>

        <p>EXAMPLE 1:</p>

        <p>/* Return value would use the default locale */<br />
        Zend_Unit.toWeight($units);</p>

        <p>EXAMPLE 2:</p>

        <p>Zend_Unit.setLocale('fr');</p>

        <p>/* Return value would use the 'fr' locale instead of the default */<br />
        Zend_Unit.toWeight($units);</p>

        <p>/* Return value would use the 'en' locale instead of the 'fr' locale */<br />
        Zend_Unit.toWeight($units, $format, 'en'); </p>

        <p>Also, <a href="http://www.onlineconversion.com/">this site</a> as a reference, as it likely has all the information you'll need in one place and possibly even other conversions you haven't thought to include yet.</p>

        1. Jun 20, 2006

          <p>I like the staticification of Zend_Unit and will change this with next wiki-update. <ac:emoticon ac:name="smile" /></p>

      2. Jun 20, 2006

        <p>I am not clear how it would look, but ultimately there are hundreds of units and the class would be HUGE in order to be complete. Also what happens with:</p>

        <p>$unit = Zend_Unit('25742.54 kg',Zend_Unit::KILOGRAM);<br />
        echo $unit->toPressure(Zend_Unit::WATT,"n.2",de_DE); // outputs ?</p>

        <p>Maybe break it up into individual static classes for each type of unit like:</p>

        <p>class Zend_Units_Weight<br />
        class Zend_Units_Length<br />
        class Zend_Units_Volume<br />
        ...</p>

        1. Jun 20, 2006

          <p>Sure there are hundreds of units.<br />
          This was the reason why I split them in types.</p>

          <p>There are only a few types like weight, lenght, temperature and so on.<br />
          These recognise their known types.</p>

          <p>The example you gave would throw 2 exeptions :</p>

          <ul>
          <li>WATT is no unit of type Pressure</li>
          <li>KILOGRAM can not be converted to WATT</li>
          </ul>

          <p>Conversion can only done between same types.</p>

          <p>When you give an type-less input all works right :</p>

          <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
          $unit = Zend_Unit('25742.54');
          echo $unit->toPower(Zend_Unit::WATT,"n.2",Zend_Locale:DE_DE); // outputs 25742,54 W
          ]]></ac:plain-text-body></ac:macro>

          <p>When split into individual classes each class will have 1 function... I don't think this is nessecary.</p>

          1. Jun 20, 2006

            <p>"When split into individual classes each class will have 1 function... I don't think this is nessecary."</p>

            <p>They would be polymorphic if the all had the same interface with a convert() method. That might be handy for something. </p>

    2. Jun 22, 2006

      <p>I really, really agree with this. Each helper class can identify itself as a weight, volume, or length, and then the conversion process can be delegated down.</p>

      1. Jun 22, 2006

        <p>So you want to have</p>

        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        class Zend_Unit_Weight extends Zend_Unit
        class Zend_Unit_Temperature extends Zend_Unit
        ]]></ac:plain-text-body></ac:macro>

        <p>and then call for example</p>

        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        $mytemperature = Zend_Unit_Temperature::toUnit('23.6°','n.2',Zend_Locale::en_UK);
        $newtemperature = Zend_Unit_Temperature::toTemperature($mytemperature, 'n.0', Zend_Locale::fr_FR);
        ]]></ac:plain-text-body></ac:macro>

        <p>.....</p>

        <p>I don't think this is handy. From the site of object orientation is makes sense, but for the user not. More tipping and less useability.</p>

        <p>But again...</p>

        <p>"How do you want the class to look like ?"</p>

        1. Jun 23, 2006

          <p>I've thought more about it. Scratch the delegating down part.</p>

          <p>> "How do you want the class to look like ?"</p>

          <p>Each unit type class would be measured (internally only) against a benchmark unit. For length it could be the meter, for volume the liter, and for weight the gram, and so on.</p>

          <p>The design goals should be:</p>

          <ul>
          <li>Zend_Unit is easy to extend</li>
          <li>Zend_Unit includes Zend_Unit_Length, Zend_Unit_Weight, etc.</li>
          <li>Users do not have to include string indicators within the number, and do not have to depend on Zend_Locale. The number is an integer or float. The return value is an integer or float. The mechanism for conversion is indicated by parameters.</li>
          </ul>

          <p>Given that, here's how I would implement it:</p>

          <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
          $lightyears = new Zend_Unit(4.3, Zend_Unit_Length::LIGHTYEAR);
          $inches = $lightyears->convertTo(Zend_Unit_Length::INCH);
          ]]></ac:plain-text-body></ac:macro>

          <p>Ta-da! <ac:emoticon ac:name="wink" /></p>

          <p>This is a more object-oriented approach than in the proposal, as well. Here's a complete class skeleton:</p>

          <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
          class Zend_Unit
          {
          private $value; // Benchmark value, not the value passed in
          private $type; // Length, weight, temperature, etc.

          /**

          • @param float Original value
          • @param int Unit type
            */
            public function __construct($value, $type);

          /**

          • @param int Unit type to convert to
          • @return float Converted value
            */
            public function convertTo($type);
            }

          class Zend_Unit_Length
          {
          const AU = 1.49598E11;
          const INCH = 0.0254;
          const FOOT = 0.3048;
          const LIGHTYEAR = 9.4605284E15;
          // Many, many, MANY other const declarations

          private function __construct() {}
          }
          ]]></ac:plain-text-body></ac:macro>

          1. Jun 24, 2006

            <p>Yep, sounds very neat and tidy. Add a vote from me.</p>

          2. Jun 24, 2006

            <p>Seperating the Types is a good approach.</p>

            <p>Looks very handy <ac:emoticon ac:name="smile" /><br />
            I will integrate this with my next reworking.</p>

            <p>BUT - as you wrote with your 3rd design goal</p>

            <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
            Users do not have to include string indicators within the number, and do not have to depend on Zend_Locale. The number is an integer or float. The return value is an integer or float. The mechanism for conversion is indicated by parameters.
            ]]></ac:plain-text-body></ac:macro>

            <p>The Zend_Unit Class was extracted from Zend_Locale, so the basic handling is the internal knowledge of locales and their formatting as these are defined in the LDML.<br />
            My approach was that the user doesn't have to be aware of something. He doesn't have to preformat the input befor he could use it within our class.<br />
            Otherwise there will be some problems. For example:</p>
            <ul>
            <li>In german the comma seperation is with "," on english with "."</li>
            <li>Working with circular values the user will have an input like 24°35'24''.</li>
            </ul>

            <p>So I will have to be aware of</p>
            <ul>
            <li>Different Input depending on locales by using Zend_Locale_Format</li>
            <li>Format the Input and the Output properly</li>
            <li>The user could wish to use a different Locale or Formatting for In- and/or Output</li>
            </ul>

            <p>To ignore this and only use real/integer values and ignore locales and formatting would only mean that all work has to be done by the user and the framework will only do the maths ignoring the needs of the users.<br />
            Of course my class could be used without handling from locales and/or formatting by the user and it will then use the default ones.</p>

            <p>Btw:<br />
            Internally I will use some kind of benchmark unit. But maybe these must be handled different (not fixed to one unit).<br />
            Think of length:<br />
            Inputs in "PICOMETER" and Inputs in "LIGHTYEARS". They can not be measured against meters, as the difference is to big !! We would have rounding errors.</p>

            <p>So to summarize for now :</p>
            <ul>
            <li>I will rework my proposal for use of type-classes (with one abstract one)</li>
            <li>I don't know if object or static approach is better... (will let this static for now)</li>
            <li>I will not strip the optional locale and formatting usage</li>
            <li>Let's discuss after rework</li>
            </ul>

            <p>PS:<br />
            Everyone comments Zend_Unit and Zend_Currency but not one comment about the base class Zend_Locale from which are all classes extracted <ac:emoticon ac:name="smile" /></p>

            1. Jun 24, 2006

              <blockquote><p>Of course my class could be used without handling from locales and/or formatting by the user and it will then use the default ones.</p></blockquote>

              <p>I really think this is the way to go. Programming languages in general expect values in US (British) format, don't they? What happens when you pass 23,3 to is_numeric?</p>

              <p>When creating a class, I look at the core of what the class is supposed to do. Usually, I find that the things I want to do that don't directly contribute instead belong in an independent class. I think this is the case with Zend_Locale. A user should be able to pass in a value and get a value, but the class should have no knowledge of whether they're in the US or Germany, because units are units are units. If their notation is different, then they should preformat in Zend_Locale.</p>

              <blockquote><p>Otherwise there will be some problems. For example ... Working with circular values the user will have an input like 24°35'24''.</p></blockquote>

              <p>I think this conversion is outside the scope of this class. Also, it seems to be the only one that requires input like this, and I would really not want to see the class be completely altered for one conversion that is easy to perform manually and requires uncommon characters (the degree symbol). You'll notice that most online forms that do this conversion have three separate fields to avoid use of the degree symbol.</p>

              <blockquote><p>Inputs in "PICOMETER" and Inputs in "LIGHTYEARS". They can not be measured against meters, as the difference is to big !! We would have rounding errors.</p></blockquote>

              <p>Did you test it?</p>

              <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
              class Test
              {
              const PICOMETER = 1e-12;
              const LIGHTYEAR = 9.4605284e15;

              public function __construct() {}

              public static function run($value, $convertFrom, $convertTo)

              Unknown macro: { $value = $value * $convertFrom; $value = $value / $convertTo; return $value; }

              }

              print Test::run(0.1, Test::PICOMETER, Test::LIGHTYEAR);
              // prints 1.0570234110814E-029 (Google says: 1.05702341E-029)
              print Test::run(0.00027, Test::PICOMETER, Test::PICOMETER);
              // prints 0.00027
              print Test::run(900000, Test::LIGHTYEAR, Test::LIGHTYEAR);
              // prints 900000
              ]]></ac:plain-text-body></ac:macro>

              <p>Works for me.</p>

              1. Jun 24, 2006

                <p>bg. Programming languages in general expect values in US (British) format, don't they? </p>
                <ul>
                <li>But my user inputs 14.411,23 as he is german... bad user <ac:emoticon ac:name="smile" /></li>
                <li>But my web-app/class known he is an german user (as the bowser sends his locale) so my class could process the<br />
                input properly. Good class <ac:emoticon ac:name="smile" /></li>
                </ul>

                <p>bg. What happens when you pass 23,3 to is_numeric?</p>
                <ul>
                <li>is_numeric doesn't know that my user is chinese and his input is different than from an english user.</li>
                <li>is_numeric is not locale-aware... the basic of my class is, that it is locale-aware.</li>
                <li>Just because the standard-php doesn't support this, doesn't mean that it is not usefull to users of the ZF.</li>
                </ul>

                <p>So you would have to parse the input format it properly so that the function can understand it.</p>

                <p>I would send the input to my function and would get the expected output without parsing or formating<br />
                by my own.</p>

                <p>bg. Did you test it?<br />
                bg. Works for me.</p>

                <p>Then it also works for me and the class will be simpler <ac:emoticon ac:name="smile" /></p>

                <p>As you may mention all the classes I proposed are locale-aware.<br />
                All these classes are often/normally used in a multi-langual situation.</p>

                <p>That was the reason for my proposal.<br />
                When I would have to strip the usefull features as locale and formatting <br />
                the classes would have no use in my eyes. <ac:emoticon ac:name="sad" /><br />
                But maybe I'm only to depressed today <ac:emoticon ac:name="wink" /></p>

                1. Jun 25, 2006

                  <p><strong>Ugh.</strong> I replied to this yesterday, but it disappeared--I am 100% positive I hit the Post button and didn't just hit Preview. It was a long post and I'm a little annoyed...</p>

                  <p>Basically, the gist was that I apparently misunderstood your purpose for using the class, and that it could be used for dynamic measurements based on the browser locale. For example, instead of saying "Such and such is 24,000 meters long", if the user was in America it might dynamically say "78,740 feet" instead. In this way, a CMS built on Zend Framework might automatically detect all units in text and automatically convert them into Zend_Unit locale-aware units by providing an additional layer on top.</p>

                  <p>So extending my previous idea:</p>

                  <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
                  $lightyears = new Zend_Unit(4.3, Zend_Unit_Length::LIGHTYEAR);
                  $inches = $lightyears->convertTo(Zend_Unit_Length::INCH);
                  ]]></ac:plain-text-body></ac:macro>

                  <p>You might also write:</p>

                  <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
                  $meters = new Zend_Unit(24000, Zend_Unit_Length::METER); // METRE should also work
                  print $meters->format($locale->getLocale()); // prints "78,740 feet"
                  ]]></ac:plain-text-body></ac:macro>

                  <p>Here's a new class skeleton along these lines. Some important functionality has changed, especially return values:</p>

                  <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
                  class Zend_Unit
                  {
                  private $benchmark; // Benchmark value, not the value passed in
                  private $value; // Numeric value
                  private $valueString; // Locale-formatted numeric value
                  private $type; // Length, weight, temperature, etc. Probably a constant.
                  private $typeString; // Plural- and locale-aware type string

                  /**

                  • @param float Original value
                  • @param int Unit type
                  • @param string Optional country code (e.g., "en_US")
                    */
                    public function __construct($value, $type [, $locale]);

                  /**

                  • @param int Unit type to convert to
                  • @param string Optional country code (e.g., "en_US")
                  • @return Zend_Unit New unit instance
                    */
                    public function convertTo($type [, $locale]);

                  /**

                  • Calls convertTo(), but passes $this->type for $type
                  • @param string Country code (e.g., "en_US")
                  • @return Zend_Unit New unit instance
                    */
                    public function format($locale);

                  /**

                  • @return float Numeric unit value ($this->value)
                    */
                    public function getValue();

                  /**

                  • @return string Formatted unit value (e.g., "12,345.67", "12.345,67")
                    */
                    public function getValueString();

                  /**

                  • @return int Internal type constant (ZEND_UNIT_LENGTH, possibly)
                    */
                    public function getType();

                  /**

                  • Returns a plural- and locale-aware type string. For example,
                  • "foot", "feet", "meter", "meters", "metre", "metres"...
                  • @return string Type string
                    */
                    public function getTypeString();

                  /**

                  • Returns a combination of getValueString() and getTypeString().
                  • @return string Full string representation (e.g., "12,345.56 feet")
                    */
                    public function toString();

                  /**

                  • Calls toString().
                  • @return string Full string representation (e.g., "12,345.56 feet")
                    */
                    public function __toString();
                    }
                    ]]></ac:plain-text-body></ac:macro>
  2. Jun 20, 2006

    <p>A concern I have is the name "Zend_Unit", my first thought went to Unit testing, What is a "Unit"</p>

    <p>Since this properly formats a "Unit" would it not make more sense for it to be part of Zend_Locale?</p>

    <p>Zend_Locale_Unit makes more sense?</p>

    1. Jun 20, 2006

      <p>The first approach was to do a "Zend_Locale_Unit".</p>

      <p>But as the other classes like Zend_Date and Zend_Currency which make extend use of Zend_Locale were all explicit extracted from Zend_Locale, it would make no sense to let the Unit Handling in Locale.</p>

      <p>Zend_Locale should ONLY handle direct Locale and Translation Issues. </p>

      <p>Conversion between Types and Type-Like-Formatting which is done by Zend_Unit has nothing to do with Locale Handling. This was the reason why to do a own Class / Proposal.</p>

      1. Jun 21, 2006

        <p>In the spirit of it-does-what-it-says, why not simply Zend_Unit_Converter or Zend_Convert?</p>

        <p>$unit = Zend_Convert::toUnit('86,7°F',Zend_Unit::FAHRENHEIT);<br />
        echo Zend_Convert::toTemperature($unit,Zend_Unit::CELSIUS);</p>

        1. Jun 21, 2006

          <p>Zend_Converter sounds handy <ac:emoticon ac:name="smile" /></p>

          <p>But it doesn't only convert, it also handles locale-formatting.</p>

          <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
          echo Zend_Unit::toWeight('23456789',Zend_Unit::POUND,,Zend_Locale::DE_DE);
          // 23.456.789 Pfund
          ]]></ac:plain-text-body></ac:macro>

          <p>I would let the desicion for changing the Class name to our Zend_Boys <ac:emoticon ac:name="smile" /><br />
          I like both.</p>

  3. Jul 17, 2006

    <ac:macro ac:name="note"><ac:parameter ac:name="title">Zend Feedback</ac:parameter><ac:rich-text-body>
    <p>Zend_Unit is conditionally accepted subject to the<br />
    conventions, stipulations, requirements, and changes listed below.</p>

    <p>A ZF default locale object should be used in most places where a<br />
    component or function expects an optional locale object.<br />
    The default locale object should be constructed from an instance of<br />
    Zend_Config shared by all ZF components.</p>

    <p>Parsing, normalization, conversion, and formatting function names<br />
    could benefit from sharing common looking names with other locale-related<br />
    classes.</p>

    <p>Why should rounding be performed during instantiation, instead of formatting?</p>

    <p>If the unit type is specified (e.g. Zend_Unit::KILOGRAM), can Zend_Unit<br />
    do the "right" thing when given a raw number like "1.250" or "12,5"?<br />
    A couple use case would help clarify this.</p>

    <p>A large majority of the world uses Celsius. Should Zend_Unit::CELSIUS<br />
    be required, if the default locale belongs to the majority?</p>

    <p>The name of the class needs clarification, probably by changing it to one of:</p>
    <ul class="alternate">
    <li>Zend_UnitConversion</li>
    <li>Zend_UnitConvert</li>
    <li>Zend_MeasurementConverter (most accurate, but terrible to type)</li>
    <li>Zend_Convert</li>
    <li>Zend_Converter</li>
    <li>Zend_Measure</li>
    <li>suggestions?</li>
    </ul>

    <p>Are the Zend_Unit constants, like Zend_Unit::SOME_UNIT_TYPE, absolute,<br />
    precise, unambiguously unique designators of units, or can they represent<br />
    something more abstract? For example, "ton" has several meanings,<br />
    depending on the locale. If the units are unambigous, then what is the reason<br />
    for having both a parameter for Zend_Unit::CONSTANT_UNIT_TYPE and a<br />
    parameter for a locale in the convertTo() method?</p>

    <p>Fundamentally, we have data input, parsing, and normalization in the context<br />
    of a particular locale, followed by formatting for output according to the<br />
    conventions of optionally, a different locale.<br />
    Methods should not combine input parsing, normalization, and output<br />
    formatting all in one step. Instead, parsing and normalization could be<br />
    encapsulated by a constructor. Then a "convertTo($someLocale)" can be<br />
    applied to the instance, possibly more than once, if the same unit must<br />
    be shown in different locales. Thus, __constructor()'s methods return<br />
    normalized instances, not converted instances.</p>

    <p>Instances should be serializable.</p></ac:rich-text-body></ac:macro>

    1. Jul 18, 2006

      <blockquote>
      <p>A ZF default locale object should be used in most places where a<br />
      component or function expects an optional locale object.<br />
      The default locale object should be constructed from an instance of<br />
      Zend_Config shared by all ZF components.</p></blockquote>
      <p> All parameters witch expect a locale object are optional.<br />
      When the parameter is left empty the function will take the standard locale<br />
      which is set or recognized by ZF automatically.<br />
      Therefor all "locale" parameters are marked OPTIONAL</p>
      <blockquote>
      <p>Why should rounding be performed during instantiation, instead of formatting?</p></blockquote>
      <p>There will be no rounding or formatting by instantiation.<br />
      By instantiation the value will be extracted and stored internally in the standard type.<br />
      Formatting will only be done when requesting the output string.</p>
      <blockquote>
      <p>If the unit type is specified (e.g. Zend_Unit::KILOGRAM), can Zend_Unit<br />
      do the "right" thing when given a raw number like "1.250" or "12,5"?<br />
      A couple use case would help clarify this.</p></blockquote>
      <p>I added some new use-cases to make this clear.<br />
      Generally an integer, float or string can be given by instantiation<br />
      and the first recognised "value" will be taken but locale-aware.<br />
      That means a english '12.5' is identical with an german '12,5'.</p>
      <blockquote>
      <p>A large majority of the world uses Celsius. Should Zend_Unit::CELSIUS<br />
      be required, if the default locale belongs to the majority?</p></blockquote>
      <p>I reworked this.<br />
      You can make <strong>Zend_Measure::TEMPERATURE</strong> which will take the standard for<br />
      temperature measurements which is Celsius.<br />
      <strong>Zend_Measure_Temperature::CELSIUS</strong> is identically with <strong>Zend_Measure::TEMPERATURE</strong>.</p>
      <blockquote>
      <p>The name of the class needs clarification, probably by changing it to one of:</p>
      <ul class="alternate">
      <li>Zend_UnitConversion</li>
      <li>Zend_UnitConvert</li>
      <li>Zend_MeasurementConverter (most accurate, but terrible to type)</li>
      <li>Zend_Convert</li>
      <li>Zend_Converter</li>
      <li>Zend_Measure</li>
      <li>suggestions?</li>
      </ul>
      </blockquote>
      <p>In my eyes Zend_Measure makes all clear. Handling of all measurement related things as<br />
      getting value out of string, conversion, adding and so on.</p>
      <blockquote>
      <p>Are the Zend_Unit constants, like Zend_Unit::SOME_UNIT_TYPE, absolute,<br />
      precise, unambiguously unique designators of units, or can they represent<br />
      something more abstract? For example, "ton" has several meanings,<br />
      depending on the locale. If the units are unambigous, then what is the reason<br />
      for having both a parameter for Zend_Unit::CONSTANT_UNIT_TYPE and a<br />
      parameter for a locale in the convertTo() method?</p></blockquote>
      <p>The constants are absolute and precise units.<br />
      There are no double units.<br />
      When there are locale dependent units as feet the class will have<br />
      <strong>FEET, FEET_FRENCH, FEET_EGYPT, FEET_IRAQ</strong><br />
      as all feet's are calculated different. But there will always an international standard <strong>FEET</strong> unit.</p>

      <p>To mention:<br />
      Zend_Measure can only recognize input values.<br />
      It does not know "Celsius" and maybe "Celsian".<br />
      It only knows "1234" as this is locale independant.<br />
      When given "1234 Celsius" only 1234 would be recognised,<br />
      so you have to say which expected type you are instantiating.</p>

      <p>The type parameter in the convertTo method can be used to change the<br />
      unit type, so instead of METER we can produce LIGHT_SECOND output<br />
      of the object value. So 100,000,000 meter would become 1 light second.</p>

      <p>Otherwise the locale parameter is used to know how a string has to be parsed.<br />
      Grouping in english ','  in german '.'<br />
      Decimalpoint in english '.'    in german ','<br />
      Also different number formats can be defined in the locale.<br />
      For example there are slangs which group by 5 instead of 3 as it will be done in english.<br />
      So 14,000,000 would become 140,00000.</p>
      <blockquote>
      <p>Fundamentally, we have data input, parsing, and normalization in the context<br />
      of a particular locale, followed by formatting for output according to the<br />
      conventions of optionally, a different locale.<br />
      Methods should not combine input parsing, normalization, and output<br />
      formatting all in one step. Instead, parsing and normalization could be<br />
      encapsulated by a constructor. Then a "convertTo($someLocale)" can be<br />
      applied to the instance, possibly more than once, if the same unit must<br />
      be shown in different locales. Thus, __constructor()'s methods return<br />
      normalized instances, not converted instances.</p></blockquote>
      <p>Extraction of the right value and normalization to the standardunit will be done in an extra function "extractValue".<br />
      As normalization is different for different types the encapsulating would be a problem, as each type must be normalized in an other way.<br />
      Length "12,345678m"    Circular "12'34"5678°"    Currency "$ 12.345,678"</p>

      <p>Internally the values are always stored in standard unit.</p>
      <blockquote>
      <p>Instances should be serializable.</p></blockquote>
      <p>I added this in my proposal.</p>

      <hr />
      <p>I hope I did'nt forgot something, but I think all questions should be answered.</p>

    2. Jul 18, 2006

      <p>1 thing i forgot to mention:</p>

      <p>The method "extractValue" makes use of Zend_Locale_Format->getNumber<br />
      to extract the proper value.</p>

      <p>But special values as circular must be parsed locally.<br />
      Currency on the other hand can be pased using Zend_Locale_Format->getNumber<br />
      as there is no difference in the parsing algorithmus.</p>

      <p>Hope this clears the point of confusion <ac:emoticon ac:name="smile" /></p>

      1. Jul 19, 2006

        <p>Looks good. Yes, I see that convertTo() must take 3 parameters, so that the number can be parsed correctly, and the unit of measurement must be specified independently of the data and number format (locale).</p>

  4. Aug 08, 2006

    <p>Hi all,</p>

    <p>I had some questions over Zend_Measure I thought to share:</p>

    <p>Zend_Measure_Capacity - Is "capacity" really a de facto synonym of<br />
    "capacitance?" Despite the answer, I would prefer the name<br />
    Zend_Measure_Capacitance, so as to avoid ambiguity - when I first read<br />
    "Capacity," I assumed it was for volume, until I saw Zend_Measure_Volume.</p>

    <p>Zend_Measure_Flow_* - has a class for Mass; will Mass be included in<br />
    Zend_Measure (as well as Zend_Measure_Flow)? I didn't see one in the<br />
    proposal...</p>

    <p>Zend_Measure_(Illumination|Lightness) - I don't recall from physics what<br />
    the difference here might be. I did notice that several of the units<br />
    seem to be very similar across the two classes (e.g.,<br />
    Lightness::CANDELA_PER_SQUARE_METER and<br />
    Illumination::LUMEN_PER_SQUARE_METER).</p>

    <p>Best regards,<br />
    Darby</p>

    1. Aug 08, 2006

      <blockquote>
      <p>Zend_Measure_Capacity - Is "capacity" really a de facto synonym of<br />
      "capacitance?" Despite the answer, I would prefer the name<br />
      Zend_Measure_Capacitance, so as to avoid ambiguity - when I first read<br />
      "Capacity," I assumed it was for volume, until I saw Zend_Measure_Volume.</p></blockquote>
      <p>Checked <ac:emoticon ac:name="cheeky" /><br />
      I will change this soon</p>
      <blockquote>
      <p>Zend_Measure_Flow_* - has a class for Mass; will Mass be included in<br />
      Zend_Measure (as well as Zend_Measure_Flow)? I didn't see one in the<br />
      proposal...</p></blockquote>
      <p>Fluidicy is measured in<br />
      Flow of mass (f.e. flowing of sand / non fluid)<br />
      Flow of mole (includes density of flowing material)<br />
      Flow of Volume (f.e. flowing of water / fluids)</p>

      <p>As mass and volume could be seen as weight and volume I had to make a own subclass to make things clear.</p>

      <blockquote>
      <p>Zend_Measure_(Illumination|Lightness) - I don't recall from physics what<br />
      the difference here might be. I did notice that several of the units<br />
      seem to be very similar across the two classes (e.g.,<br />
      Lightness::CANDELA_PER_SQUARE_METER and<br />
      Illumination::LUMEN_PER_SQUARE_METER).</p></blockquote>

      <p>I didn't see any relationship in this 2 classes.<br />
      Lightness - f.e. Candela/m² measures the density of light.<br />
      Illumination - f.e. Lumen/m² measures the energy of light</p>

      <p>Otherwise described:</p>

      <p>Lightness is measured in Lightpower per Square meter... how much power of light per room-angle is found.<br />
      Illumination is measured in Lightenergy per Square meter... how much energy of light per room-angle is found.<br />
      Only because both units are measured per room-angle doesn't mean that they can be converted into each other without the knowledge of a third parameter.</p>

      <p>To get Lumen from Candela (Lightness to Illumination) you would have to multiply candela with<br />
      sterad (which is area in m² per square angle in m².</p>

      1. Aug 09, 2006

        <p>Thanks for the clarifications, Thomas! <ac:emoticon ac:name="smile" /></p>

  5. Sep 09, 2006

    <p>Great work on putting everything together and getting it approved, Thomas!</p>

    <p>One comment: Zend_Measure::sub() should just be written out as Zend_Measure::subtract(). "Sub" is probably needlessly short and obfuscated.</p>

    <p>-Matt</p>

    1. Sep 09, 2006

      <p>Thanks <ac:emoticon ac:name="smile" /></p>

      <p>Regarding to sub():<br />
      In all locale aware classes the mathematical functions are abbreviated to 3 letters:</p>

      <p>add() for addition and sub() for substraction.</p>

      <p>Changing sub to substract would mean</p>
      <ul>
      <li>more typing for user</li>
      <li>change all other locale related classes...</li>
      </ul>

      <p>Speaking for the Zend_Date class I'm actual coding that all subxxx functions will change. And there are much of them <ac:emoticon ac:name="wink" /></p>

      <p>subDay would become substractDay<br />
      subYear would become substractYear</p>

      <p>and so on...<br />
      I think for "add" and "sub" the abbreviation can be used as the meaning is clear.</p>

      <p>Greetings<br />
      Thomas</p>

  6. Jan 25, 2007

    <ac:macro ac:name="note"><ac:parameter ac:name="title">Zend Feedback</ac:parameter><ac:rich-text-body>
    <p>Hi Thomas,</p>

    <p>This change has been approved. The complications are resolved,<br />
    if users simply use the needed Measure class directly.</p>

    <p>We will need to update the proposal and documentation.</p>

    <p>Cheers,<br />
    Gavin</p>

    <p>> -------- Original Message --------<br />
    > Subject: Re: <ac:link><ri:page ri:content-title="fw-i18n" /></ac:link> RE: <ac:link><ri:page ri:content-title="fw-general" /></ac:link> Zend_Measure constants wrong?<br />
    > Date: Wed, 24 Jan 2007 00:15:00 +0100<br />
    > From: Thomas Weidner <thomas.weidner@gmx.at><br />
    ><br />
    > Hy Andi and Team,<br />
    ><br />
    > .<br />
    > .<br />
    ><br />
    > We could also negate the base class...<br />
    > So a user would have to use Zend_Measure_Length direct instead of Zend_Measure...<br />
    > No base class, no problems <ac:emoticon ac:name="smile" /><br />
    > Would be a good solution in my eyes... it's only the question if this is coding standard conform...<br />
    ><br />
    ><br />
    > .<br />
    > .</p></ac:rich-text-body></ac:macro>