├── .editorconfig ├── .eslintrc.json ├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.md │ ├── change-request.md │ └── config.yml ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── ci.yml ├── .gitignore ├── .tidyrc.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── bower.json ├── docs └── README.md ├── package.json ├── packages.dhall ├── spago.dhall ├── src └── Effect │ ├── Now.js │ └── Now.purs └── test └── Main.purs /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { "browser": true }, 3 | "extends": "eslint:recommended", 4 | "parserOptions": { "ecmaVersion": 6, "sourceType": "module" }, 5 | "rules": { 6 | "block-scoped-var": "error", 7 | "consistent-return": "error", 8 | "eqeqeq": "error", 9 | "guard-for-in": "error", 10 | "no-bitwise": "error", 11 | "no-caller": "error", 12 | "no-extra-parens": "off", 13 | "no-extend-native": "error", 14 | "no-loop-func": "error", 15 | "no-new": "error", 16 | "no-param-reassign": "error", 17 | "no-return-assign": "error", 18 | "no-sequences": "error", 19 | "no-unused-expressions": "error", 20 | "no-use-before-define": "error", 21 | "no-undef": "error", 22 | "no-eq-null": "error", 23 | "radix": ["error", "always"], 24 | "indent": ["error", 2, { "SwitchCase": 1 }], 25 | "quotes": ["error", "double"], 26 | "semi": ["error", "always"], 27 | "strict": ["error", "global"] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report an issue 4 | title: "" 5 | labels: bug 6 | assignees: "" 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of the bug. 11 | 12 | **To Reproduce** 13 | A minimal code example (preferably a runnable example on [Try PureScript](https://try.purescript.org)!) or steps to reproduce the issue. 14 | 15 | **Expected behavior** 16 | A clear and concise description of what you expected to happen. 17 | 18 | **Additional context** 19 | Add any other context about the problem here. 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/change-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Change request 3 | about: Propose an improvement to this library 4 | title: "" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | **Is your change request related to a problem? Please describe.** 10 | A clear and concise description of the problem. 11 | 12 | Examples: 13 | 14 | - It's frustrating to have to [...] 15 | - I was looking for a function to [...] 16 | 17 | **Describe the solution you'd like** 18 | A clear and concise description of what a good solution to you looks like, including any solutions you've already considered. 19 | 20 | **Additional context** 21 | Add any other context about the change request here. 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: PureScript Discourse 4 | url: https://discourse.purescript.org/ 5 | about: Ask and answer questions on the PureScript discussion forum. 6 | - name: PureScript Discord 7 | url: https://purescript.org/chat 8 | about: Ask and answer questions on the PureScript chat. 9 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Description of the change** 2 | Clearly and concisely describe the purpose of the pull request. If this PR relates to an existing issue or change proposal, please link to it. Include any other background context that would help reviewers understand the motivation for this PR. 3 | 4 | --- 5 | 6 | **Checklist:** 7 | 8 | - [ ] Added the change to the changelog's "Unreleased" section with a link to this PR and your username 9 | - [ ] Linked any existing issues or proposals that this pull request should close 10 | - [ ] Updated or added relevant documentation in the README and/or documentation directory 11 | - [ ] Added a test for the contribution (if applicable) 12 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - name: Set up PureScript toolchain 17 | uses: purescript-contrib/setup-purescript@main 18 | with: 19 | purescript: "unstable" 20 | purs-tidy: "latest" 21 | 22 | - name: Cache PureScript dependencies 23 | uses: actions/cache@v2 24 | with: 25 | key: ${{ runner.os }}-spago-${{ hashFiles('**/*.dhall') }} 26 | path: | 27 | .spago 28 | output 29 | 30 | - name: Set up Node toolchain 31 | uses: actions/setup-node@v2 32 | with: 33 | node-version: "14.x" 34 | 35 | - name: Cache NPM dependencies 36 | uses: actions/cache@v2 37 | env: 38 | cache-name: cache-node-modules 39 | with: 40 | path: ~/.npm 41 | key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package.json') }} 42 | restore-keys: | 43 | ${{ runner.os }}-build-${{ env.cache-name }}- 44 | ${{ runner.os }}-build- 45 | ${{ runner.os }}- 46 | 47 | - name: Install NPM dependencies 48 | run: npm install 49 | 50 | - name: Build the project 51 | run: npm run build 52 | 53 | - name: Run tests 54 | run: npm run test 55 | 56 | - name: Check formatting 57 | run: purs-tidy check src test 58 | 59 | - name: Verify Bower & Pulp 60 | run: | 61 | npm install bower pulp@16.0.0-0 62 | npx bower install 63 | npx pulp build -- --censor-lib --strict 64 | if [ -d "test" ]; then 65 | npx pulp test 66 | fi 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | !.gitignore 3 | !.github 4 | !.editorconfig 5 | !.tidyrc.json 6 | !.eslintrc.json 7 | 8 | output 9 | generated-docs 10 | bower_components 11 | 12 | node_modules 13 | package-lock.json 14 | *.lock 15 | -------------------------------------------------------------------------------- /.tidyrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "importSort": "source", 3 | "importWrap": "source", 4 | "indent": 2, 5 | "operatorsFile": null, 6 | "ribbon": 1, 7 | "typeArrowPlacement": "first", 8 | "unicode": "never", 9 | "width": null 10 | } 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | Notable changes to this project are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 4 | 5 | ## [Unreleased] 6 | 7 | Breaking changes: 8 | 9 | New features: 10 | 11 | Bugfixes: 12 | 13 | Other improvements: 14 | 15 | ## [v6.0.0](https://github.com/purescript-contrib/purescript-now/releases/tag/v6.0.0) - 2022-04-27 16 | 17 | Breaking changes: 18 | - Migrate FFI to ES modules (#25 by @JordanMartinez) 19 | 20 | New features: 21 | 22 | Bugfixes: 23 | 24 | Other improvements: 25 | - Added `purs-tidy` formatter (#23 by @thomashoneyman) 26 | - Added tests (#20 by @ntwilson) 27 | - Added quick start (#22 by @maxdeviant) 28 | 29 | ## [v5.0.0](https://github.com/purescript-contrib/purescript-now/releases/tag/v5.0.0) - 2021-02-26 30 | 31 | Breaking changes: 32 | - Added support for PureScript 0.14 and dropped support for all previous versions (#17) 33 | 34 | New features: 35 | - Added `getTimezoneOffset` (#13 by @cmdv) 36 | 37 | Bugfixes: 38 | 39 | Other improvements: 40 | - Changed default branch to `main` from `master` 41 | - Updated to comply with Contributors library guidelines by adding new issue and pull request templates, updating documentation, and migrating to Spago for local development and CI (#14 by @maxdeviant) 42 | 43 | ## [v4.0.0](https://github.com/purescript-contrib/purescript-now/releases/tag/v4.0.0) - 2018-05-25 44 | 45 | - Updated for PureScript 0.12 46 | 47 | ## [v3.0.0](https://github.com/purescript-contrib/purescript-now/releases/tag/v3.0.0) - 2017-04-03 48 | 49 | - Updated for PureScript 0.11 50 | 51 | ## [v2.0.0](https://github.com/purescript-contrib/purescript-now/releases/tag/v2.0.0) - 2016-10-17 52 | 53 | - Updated dependencies 54 | 55 | ## [v1.0.0](https://github.com/purescript-contrib/purescript-now/releases/tag/v1.0.0) - 2016-06-09 56 | 57 | - Initial release. 58 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Now 2 | 3 | Thanks for your interest in contributing to `now`! We welcome new contributions regardless of your level of experience or familiarity with PureScript. 4 | 5 | Every library in the Contributors organization shares a simple handbook that helps new contributors get started. With that in mind, please [read the short contributing guide on purescript-contrib/governance](https://github.com/purescript-contrib/governance/blob/main/contributing.md) before contributing to this library. 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 PureScript 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Now 2 | 3 | [![CI](https://github.com/purescript-contrib/purescript-now/workflows/CI/badge.svg?branch=main)](https://github.com/purescript-contrib/purescript-now/actions?query=workflow%3ACI+branch%3Amain) 4 | [![Release](https://img.shields.io/github/release/purescript-contrib/purescript-now.svg)](https://github.com/purescript-contrib/purescript-now/releases) 5 | [![Pursuit](https://pursuit.purescript.org/packages/purescript-now/badge)](https://pursuit.purescript.org/packages/purescript-now) 6 | [![Maintainer: garyb](https://img.shields.io/badge/maintainer-garyb-teal.svg)](https://github.com/garyb) 7 | 8 | Effect type and function for accessing the current machine's date and time. 9 | 10 | ## Installation 11 | 12 | Install `now` with [Spago](https://github.com/purescript/spago): 13 | 14 | ```sh 15 | spago install now 16 | ``` 17 | 18 | ## Quick start 19 | 20 | The functions provided by `now` can be used to get the current date and time from the current machine's system clock. 21 | 22 | Here are two example functions that print out the current year and time: 23 | 24 | ```purs 25 | import Prelude 26 | import Data.DateTime 27 | import Data.Enum 28 | import Effect 29 | import Effect.Console 30 | import Effect.Now 31 | 32 | printCurrentYear :: Effect Unit 33 | printCurrentYear = do 34 | currentDate <- nowDate 35 | let 36 | currentYear = fromEnum $ year currentDate :: Int 37 | log $ "The current year is " <> show currentYear 38 | 39 | printCurrentTime :: Effect Unit 40 | printCurrentTime = do 41 | currentTime <- nowTime 42 | let 43 | currentHour = fromEnum $ hour currentTime :: Int 44 | currentMinute = fromEnum $ minute currentTime :: Int 45 | log $ "The current time is " <> show currentHour <> ":" <> show currentMinute 46 | ``` 47 | 48 | We can then try these functions out in a REPL: 49 | 50 | ``` 51 | > printCurrentYear 52 | The current year is 2021 53 | 54 | > printCurrentTime 55 | The current time is 1:54 56 | ``` 57 | 58 | ## Documentation 59 | 60 | `now` documentation is stored in a few places: 61 | 62 | 1. Module documentation is [published on Pursuit](https://pursuit.purescript.org/packages/purescript-now). 63 | 2. Written documentation is kept in the [docs directory](./docs). 64 | 3. Usage examples can be found in [the test suite](./test). 65 | 66 | If you get stuck, there are several ways to get help: 67 | 68 | - [Open an issue](https://github.com/purescript-contrib/purescript-now/issues) if you have encountered a bug or problem. 69 | - Ask general questions on the [PureScript Discourse](https://discourse.purescript.org) forum or the [PureScript Discord](https://purescript.org/chat) chat. 70 | 71 | ## Contributing 72 | 73 | You can contribute to `now` in several ways: 74 | 75 | 1. If you encounter a problem or have a question, please [open an issue](https://github.com/purescript-contrib/purescript-now/issues). We'll do our best to work with you to resolve or answer it. 76 | 77 | 2. If you would like to contribute code, tests, or documentation, please [read the contributor guide](./CONTRIBUTING.md). It's a short, helpful introduction to contributing to this library, including development instructions. 78 | 79 | 3. If you have written a library, tutorial, guide, or other resource based on this package, please share it on the [PureScript Discourse](https://discourse.purescript.org)! Writing libraries and learning resources are a great way to help this library succeed. 80 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "purescript-now", 3 | "homepage": "https://github.com/purescript-contrib/purescript-now", 4 | "description": "PureScript library for reading the current date and time value", 5 | "license": "MIT", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/purescript-contrib/purescript-now.git" 9 | }, 10 | "ignore": [ 11 | "**/.*", 12 | "bower_components", 13 | "node_modules", 14 | "output", 15 | "bower.json", 16 | "package.json" 17 | ], 18 | "dependencies": { 19 | "purescript-datetime": "^6.0.0", 20 | "purescript-effect": "^4.0.0" 21 | }, 22 | "devDependencies": { 23 | "purescript-assert": "^6.0.0", 24 | "purescript-console": "^6.0.0", 25 | "purescript-either": "^6.0.0", 26 | "purescript-exceptions": "^6.0.0", 27 | "purescript-node-process": "^9.0.0", 28 | "purescript-prelude": "^6.0.0", 29 | "purescript-transformers": "^6.0.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Now Documentation 2 | 3 | This directory contains documentation for `now`. If you are interested in contributing new documentation, please read the [contributor guidelines](../CONTRIBUTING.md) and [What Nobody Tells You About Documentation](https://documentation.divio.com) for help getting started. 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "build": "eslint src && spago build --purs-args '--censor-lib --strict'", 5 | "test": "spago test --no-install" 6 | }, 7 | "devDependencies": { 8 | "eslint": "^7.6.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages.dhall: -------------------------------------------------------------------------------- 1 | let upstream = 2 | https://raw.githubusercontent.com/purescript/package-sets/prepare-0.15/src/packages.dhall 3 | 4 | in upstream 5 | -------------------------------------------------------------------------------- /spago.dhall: -------------------------------------------------------------------------------- 1 | { name = "now" 2 | , dependencies = 3 | [ "assert" 4 | , "console" 5 | , "datetime" 6 | , "effect" 7 | , "either" 8 | , "exceptions" 9 | , "node-process" 10 | , "prelude" 11 | , "transformers" 12 | ] 13 | , packages = ./packages.dhall 14 | , sources = [ "src/**/*.purs", "test/**/*.purs" ] 15 | } 16 | -------------------------------------------------------------------------------- /src/Effect/Now.js: -------------------------------------------------------------------------------- 1 | export function now() { 2 | return Date.now(); 3 | } 4 | 5 | export function getTimezoneOffset() { 6 | var n = new Date(Date.now()); 7 | return n.getTimezoneOffset(); 8 | } 9 | -------------------------------------------------------------------------------- /src/Effect/Now.purs: -------------------------------------------------------------------------------- 1 | module Effect.Now 2 | ( now 3 | , nowDateTime 4 | , nowDate 5 | , nowTime 6 | , getTimezoneOffset 7 | ) where 8 | 9 | import Prelude 10 | 11 | import Data.DateTime (Date, DateTime, Time, date, time) 12 | import Data.Time.Duration (Minutes) 13 | import Data.DateTime.Instant (Instant, toDateTime) 14 | import Effect (Effect) 15 | 16 | -- | Gets an `Instant` value for the date and time according to the current 17 | -- | machine’s clock. 18 | foreign import now :: Effect Instant 19 | 20 | -- | Gets a `DateTime` value for the date and time according to the current 21 | -- | machine’s clock. 22 | nowDateTime :: Effect DateTime 23 | nowDateTime = toDateTime <$> now 24 | 25 | -- | Gets the date according to the current machine’s clock. 26 | nowDate :: Effect Date 27 | nowDate = date <<< toDateTime <$> now 28 | 29 | -- | Gets the time according to the current machine’s clock. 30 | nowTime :: Effect Time 31 | nowTime = time <<< toDateTime <$> now 32 | 33 | -- | Gets the time zone difference, in minutes, from current local (host system settings) to UTC using `now`. 34 | foreign import getTimezoneOffset :: Effect Minutes 35 | -------------------------------------------------------------------------------- /test/Main.purs: -------------------------------------------------------------------------------- 1 | module Test.Main where 2 | 3 | import Prelude 4 | 5 | import Control.Monad.Error.Class (try) 6 | import Control.Monad.State (StateT, execStateT, lift, modify) 7 | import Data.Either (Either(..)) 8 | import Data.Time.Duration (Minutes(..)) 9 | import Effect (Effect) 10 | import Effect.Class.Console (log, logShow) 11 | import Effect.Exception (throw) 12 | import Effect.Now (getTimezoneOffset, now, nowDate, nowTime) 13 | import Node.Process (exit) 14 | import Test.Assert (assert, assert') 15 | 16 | type FailedTestCount = Int 17 | type Test = StateT FailedTestCount Effect Unit 18 | 19 | test :: String -> Effect Unit -> Test 20 | test name body = 21 | try (lift body) >>= case _ of 22 | Right _ -> log ("✔️ " <> name) 23 | Left err -> do 24 | log ("❌ " <> name) 25 | logShow err 26 | void $ modify (_ + 1) 27 | 28 | assertDoesNotThrow :: forall a. Effect a -> Effect Unit 29 | assertDoesNotThrow action = try action >>= case _ of 30 | Right _ -> pure unit 31 | Left err -> do throw ("Expected to not throw an exception, but one was thrown.\n" <> show err) 32 | 33 | timeAdvances :: forall time. Show time => Ord time => Effect time -> String -> Test 34 | timeAdvances getTime name = test ("time advances with " <> name) do 35 | startTime <- getTime 36 | endTime <- getTime 37 | assert' (show endTime <> " should be greater than than " <> show startTime) $ endTime >= startTime 38 | 39 | canGetTheCurrentTime :: Test 40 | canGetTheCurrentTime = test "can get the current time" do 41 | assertDoesNotThrow nowTime 42 | 43 | offsetSeemsSensible :: Test 44 | offsetSeemsSensible = test "UTC offset between -13:00 and +15:00" do 45 | minutes <- getTimezoneOffset 46 | assert $ between lbound ubound minutes 47 | 48 | where 49 | lbound = Minutes $ (-13.0) * minPerHour 50 | ubound = Minutes $ 15.0 * minPerHour 51 | minPerHour = 60.0 52 | 53 | main :: Effect Unit 54 | main = do 55 | failedTests <- flip execStateT 0 do 56 | timeAdvances now "now" 57 | timeAdvances nowDate "nowDate" 58 | canGetTheCurrentTime 59 | offsetSeemsSensible 60 | 61 | exit failedTests 62 | 63 | --------------------------------------------------------------------------------